2009-02-11 20 views
22

Nói rằng tôi có một enum với bốn giá trị:Làm thế nào tôi có thể điền một hộp kết hợp WPF trong XAML với tất cả các mục từ một enum đã cho?

public enum CompassHeading 
{ 
    North, 
    South, 
    East, 
    West 
} 

gì XAML sẽ được yêu cầu để có một ComboBox được dân cư với các mặt hàng này?

<ComboBox ItemsSource="{Binding WhatGoesHere???}" /> 

Lý tưởng nhất là tôi sẽ không phải thiết lập mã C# cho việc này.

+0

Tôi vừa đọc bài viết gần đây của Eric Burke về một lớp Swing JComboBox thực hiện điều này, và nghĩ "Này, tôi thề tôi đã thấy một câu hỏi SO về điều này ..." Tôi đã gần, nhưng bạn muốn WPF, chứ không phải Java/Swing . Dù sao, ở đây nó là dành cho hậu thế: http://stuffthathappens.com/blog/2009/02/10/a-swing-jcombobox-for-enums/ – JMD

Trả lời

23

Bạn có thể sử dụng ObjectDataProvider để làm điều này:

<ObjectDataProvider MethodName="GetValues" 
    ObjectType="{x:Type sys:Enum}" x:Key="odp"> 
    <ObjectDataProvider.MethodParameters> 
     <x:Type TypeName="local:CompassHeading"/> 
    </ObjectDataProvider.MethodParameters> 
</ObjectDataProvider> 

<ComboBox ItemsSource="{Binding Source={StaticResource odp}}" /> 

Tôi tìm thấy giải pháp ở đây:

http://bea.stollnitz.com/blog/?p=28

+0

Cảm ơn, giải pháp này dường như làm việc tốt với ràng buộc TwoWay. Lưu ý rằng IsSynchronizedWithCurrentItem = "true" là một cá trích đỏ cho câu hỏi này (bạn có thể muốn loại bỏ nó để làm rõ các khách truy cập khác). –

+1

Điều này không hỗ trợ bản địa hóa. – Guge

+1

@Guge: Không, không, nhưng liệt kê cũng không hỗ trợ bản địa hóa. Bạn sẽ phải tạo một liệt kê khác nhau cho từng địa phương, hoặc bạn sẽ phải đính kèm một thuộc tính có thể tạo ra các giá trị bản địa hóa cho bạn (nó sẽ sử dụng một tra cứu có khóa), trong trường hợp này, câu hỏi và câu trả lời là không ' t áp dụng nữa. – casperOne

6

Here là một ví dụ chi tiết về làm thế nào để liên kết với enums trong WPF

Giả sử bạn có enum sau

public enum EmployeeType  
{ 
    Manager, 
    Worker 
} 

Sau đó bạn có thể liên kết trong codebehind

typeComboBox.ItemsSource = Enum.GetValues(typeof(EmployeeType)); 

hoặc sử dụng ObjectDataProvider

<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="sysEnum"> 
    <ObjectDataProvider.MethodParameters> 
     <x:Type TypeName="local:EmployeeType" /> 
    </ObjectDataProvider.MethodParameters> 
</ObjectDataProvider> 

và bây giờ bạn có thể ràng buộc trong đánh dấu

<ComboBox ItemsSource="{Binding Source={StaticResource sysEnum}}" /> 

Ngoài ra kiểm tra: Databinding an enum property to a ComboBox in WPF

1

Giải pháp thứ ba:

Đây là công việc tăng thêm một chút, tốt hơn là dễ dàng hơn trong thời gian dài nếu bạn đang ràng buộc tải trọng của Enums. Sử dụng một Trình biến đổi lấy kiểu liệt kê làm một tham số và chuyển đổi nó thành một chuỗi các chuỗi như là một đầu ra.

Trong VB.NET:

Public Class EnumToNamesConverter 
    Implements IValueConverter 

    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert 
     Return [Enum].GetNames(DirectCast(value, Type)) 
    End Function 

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack 
     Throw New NotImplementedException() 
    End Function 
End Class 

Hoặc trong C#:

public sealed class EnumToNamesConverter : IValueConverter 
{ 
    object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
    return Enum.GetNames(value.GetType()); 
    } 

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
    throw New NotSupportedException() 
    } 
} 

Sau đó, trong Application.xaml của bạn, thêm một nguồn lực toàn cầu để truy cập chuyển đổi này:

<local:EnumToNamesConverter x:Key="EnumToNamesConverter" /> 

Cuối cùng sử dụng bộ chuyển đổi trong bất kỳ trang XAML nào mà bạn cần các giá trị của bất kỳ Enum nào ...

<ComboBox ItemsSource="{Binding 
         Source={x:Type local:CompassHeading}, 
         Converter={StaticResource EnumToNamesConverter}}" /> 
+0

Hi maranite2, tôi thích giao diện của giải pháp này nhưng tôi không thể làm cho nó hoạt động với tính năng ràng buộc TwoWay.Các ràng buộc hoạt động từ kiểm soát đến dữ liệu (khi tôi lưu) nhưng nó không hoạt động từ dữ liệu để kiểm soát (hộp combo ban đầu là trống nơi có nên có một giá trị được chọn). –

3

Đối với một bước-by-step hương của lựa chọn thay thế và Mục từ của kỹ thuật, hãy thử trang web này:

The Missing .NET #7: Displaying Enums in WPF

Bài viết này chứng minh một phương pháp trọng trình bày các giá trị nhất định là tốt . Đọc tốt với nhiều mẫu mã.

14

Tôi nghĩ rằng sử dụng một ObjectDataProvider để làm điều đó là thực sự tẻ nhạt ... Tôi có một gợi ý ngắn gọn hơn (có tôi biết, đó là một chút muộn ...), sử dụng một phần mở rộng đánh dấu:

<ComboBox ItemsSource="{local:EnumValues local:EmployeeType}"/> 

Dưới đây là mã cho phần mở rộng đánh dấu:

[MarkupExtensionReturnType(typeof(object[]))] 
public class EnumValuesExtension : MarkupExtension 
{ 
    public EnumValuesExtension() 
    { 
    } 

    public EnumValuesExtension(Type enumType) 
    { 
     this.EnumType = enumType; 
    } 

    [ConstructorArgument("enumType")] 
    public Type EnumType { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     if (this.EnumType == null) 
      throw new ArgumentException("The enum type is not set"); 
     return Enum.GetValues(this.EnumType); 
    } 
} 
+0

Tôi đã đưa ra một lớp học gần chính xác với bạn khi thấy bạn. Mine thêm một kiểm tra nữa: 'enumType.IsEnum' trước câu lệnh return. –

3

đây có thể là như chửi thề trong nhà thờ, nhưng tôi muốn tuyên bố mỗi ComboBoxItem rõ ràng trong XAML vì những lý do sau đây:

  • Nếu tôi cần bản địa hóa, tôi có thể cung cấp cho XAML một người dịch và giữ mã cho chính tôi.
  • Nếu tôi có giá trị enum không phù hợp với một ComboBox đã cho, tôi không phải hiển thị chúng.
  • Thứ tự của enums được xác định trong XAML, không nhất thiết phải trong mã.
  • Số lượng giá trị enum để chọn thường không cao. Tôi sẽ xem xét Enums với hàng trăm giá trị một mùi mã.
  • Nếu tôi cần đồ họa hoặc trang trí khác trên một số các ComboBoxItems, nó sẽ là dễ nhất để chỉ cần đặt nó trong XAML, nơi nó thuộc về thay vì một số công cụ Template/Trigger khó khăn.
  • Keep It Simple, Stupid

C# mã mẫu: Mã

public enum number { one, two, three }; 

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
    } 

    private number _number = number.one; 
    public number Number 
    { 
     get { return _number; } 
     set { 
      if (_number == value) 
       return; 
      _number = value; 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs("Number")); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

XAML:

<Window x:Class="WpfApplication6.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="480" Width="677"> 
<Grid> 
    <ComboBox SelectedValue="{Binding Number}" SelectedValuePath="Tag"> 
     <ComboBoxItem Content="En" Tag="One"/> 
     <ComboBoxItem Content="To" Tag="Two"/> 
     <ComboBoxItem Content="Tre" Tag="Three"/> 
    </ComboBox> 
</Grid> 

Như bạn có thể thấy, XAML đã được bản địa hoá để Na Uy, không cần thay đổi mã C#.

+1

Và bạn nhận được hỗ trợ thiết kế thời gian ra khỏi hộp – surfen

Các vấn đề liên quan