2011-08-26 26 views
5

Tôi có một mô hình có thuộc tính enum (trong trường hợp này, liên quan đến Quy định kiểm soát xuất khẩu). Khi hiển thị giá trị cho người dùng, tôi muốn hiển thị một chuỗi tương ứng. Đôi khi điều này là trong ComboBox (nơi người dùng có thể chọn một giá trị), và đôi khi nó là trong một TextBlock (nơi nó là chỉ đọc).Bind textblock vào giá trị từ điển cho khóa trong XAML?

Ví dụ: đối với ExportRegulationType.EAR, tôi muốn hiển thị "EAR", trong khi đối với ExportRegulationType.DoNotExport, tôi muốn hiển thị "Do Not Export". Lưu ý rằng tôi không có bất kỳ nhu cầu ngôn ngữ nào, nhưng tôi nhận ra vấn đề này ...

Hiện tại, trong ViewModel, tôi có thuộc tính trả về chuỗi dựa trên giá trị enum hiện tại và cũng là một thuộc tính khác trả về một số Dictionary<ExportRegulationType, string>. Đối với ComboBoxes, tôi có thể liên kết ItemsSource với thuộc tính từ điển và đối với TextBlocks, tôi có thể liên kết với thuộc tính chuỗi. Điều này hoạt động, nhưng là loại vụng về.

Hai câu hỏi:

1) Dường như với tôi rằng tôi sẽ có thể tuyên bố từ điển (với các phím và các giá trị) như một nguồn lực tĩnh trong XAML (có thể là trong App.xaml), và sử dụng cho ItemsSource cho phiên bản ComboBox. Tuy nhiên, tôi không thể tìm ra cách khai báo và tham chiếu một thứ như thế. Làm thế nào tôi có thể làm điều đó?

2) Giả sử ở trên là đúng chỗ, tôi nghĩ rằng tôi cũng có thể thiết lập một ràng buộc với textblock, do đó dựa trên thuộc tính enum, nó sẽ tra cứu chuỗi trong từ điển.

Tôi đã thấy các câu hỏi sau liên quan đến giá trị en2 static hoặc dynamic enum. Đầu tiên không đầy đủ và thứ hai không được trả lời ...

Đây chỉ là một XAML và sẽ cho phép tôi xóa các phương thức khỏi ViewModel của tôi (chỉ có tài sản được hiển thị ExportRegulationType được liệt kê. là những thể

chỉnh sửa: thông tin thêm:.

trong ứng dụng, tôi sẽ có nhiều bộ khác nhau của quan điểm, mô hình, và ViewModels Tuy nhiên, như các quy định kiểm soát xuất khẩu là một yêu cầu chung và nhất quán, Tôi đang sử dụng thành phần để giữ cho nó khô, ví dụ, mô hình A và B cả hai đều có một mô hình ExportControl. ViewModels A1, A2, B1 và ​​B2 sẽ ha có một ExportControlViewModel. Các khung nhìn sẽ có các điều khiển gắn với ExportControlViewModel của ViewModel của chúng. Các khung nhìn sẽ có một ComboBox hoặc một TextBlock, nhưng không phải cả hai (Tùy thuộc vào nếu người dùng có thể thay đổi giá trị).

+0

Đã thêm C# làm Thẻ để các câu trả lời có cú pháp tô sáng –

Trả lời

3

Tôi không biết điều này có hiệu quả cho trường hợp của bạn hay không, nhưng đây là giải pháp khả thi. Trong mô hình chế độ xem của bạn, hãy hiển thị thuộc tính ExportRegulationType và sau đó tạo một value converter để hiển thị chuỗi mong muốn của bạn.

Đầu tiên tạo chuyển đổi giá trị của bạn:

class ExportRegulationTypeToStringConverter: IValueConverter 
{ 
    #region IValueConverter Members 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     ExportRegulationType regType = (ExportRegulationType)value; 

     switch(regType) 
     { 
      case ExportRegulationType.EAR: 
       return "EAR"; 
      case ExportRegulationType.DoNotExport: 
       return "Do Not Export"; 

      //handle other cases 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return Binding.DoNothing; 
    } 

    #endregion 
} 

Sau đó thêm một tham chiếu đến chuyển đổi của bạn trong XAML của bạn. local là không gian tên trong đó lớp của bạn được đặt.

<local:ExportRegulationTypeToStringConverter x:Key="exportRegConverter" /> 

Cuối cùng, đặt giá trị của hộp văn bản của bạn để sử dụng trình chuyển đổi. pathToEnum là thuộc tính được hiển thị trên ViewModel loại ExportRegulationType của bạn.

<TextBlock Text="{Binding pathToEnum, Converter={StaticResource exportRegConverter}}" /> 

Sử dụng ObjectDataProvider để điền vào ComboBox với giá trị của enum.

<Window.Resources> 
<ObjectDataProvider x:Key="dataFromEnum" 
    MethodName="GetValues" ObjectType="{x:Type System:Enum}"> 
     <ObjectDataProvider.MethodParameters> 
      <x:Type TypeName="local:ExportRegulationType"/> 
     </ObjectDataProvider.MethodParameters> 
</ObjectDataProvider> 
</Window.Resources> 

Bây giờ chúng tôi tạo ComboBox và sử dụng kiểu vùng chứa với value converter để hiển thị các chuỗi mong muốn cho enum của chúng tôi.

<ComboBox ItemsSource="{Binding Source={StaticResource dataFromEnum}}"> 
    <ComboBox.ItemContainerStyle> 
     <Style TargetType="ComboBoxItem"> 
      <Setter Property="Content" Value="{Binding Converter={StaticResource exportRegConverter}}" /> 
     </Style> 
    </ComboBox.ItemContainerStyle> 
</ComboBox> 
+0

Tôi ước tôi có thể chọn hai câu trả lời; Tôi đang cho bạn tín dụng để nhanh chóng đi đúng hướng và cần thêm đại diện! – mbmcavoy

+0

Ồ, như một lưu ý: sử dụng ComboBox.ItemContainerStyle hầu như đã hoạt động - các mục trong danh sách thả xuống là chính xác. Tuy nhiên, khi một mục được chọn và trình đơn thả xuống đóng lại, giá trị enum.ToString() được hiển thị. Sử dụng Mẫu dữ liệu thay vì hoạt động chính xác. – mbmcavoy

1

Sử dụng một ObjectDataProvider sau đó ràng buộc Items của ComboBox với nó, và thiết lập "DisplayMemberPath" thành "giá trị gia tăng".

Điều này cần làm là hiển thị giá trị của từ điển, nhưng ở mã phía sau SelectedValueKeyValuePair<>.

Đối TextBlock của bạn, sử dụng một Binding sử dụng ElementName=yourcomboboxPath=SelectedItem:

<TextBlock Text="{Binding SelectedItem, ElementName=yourcombobox}" /> 

Hãy cho tôi biết làm thế nào nó đi =)

2

Thay vì Dictionary bạn có lựa chọn khác.

Xem những câu dưới đây: WPF Binding a ListBox to an enum, displaying the Description Attribute

Bạn có thể thêm một thuộc tính Description enums bạn như thế này

public enum ExportRegulationType 
{ 
    [Description("EAR")] 
    EAR, 
    [Description("Do Not Export")] 
    DoNotExport 
} 

Và khi bạn muốn hiển thị nó, bạn chỉ có thể sử dụng EnumDescriptionConverter Chuyển đổi được tìm thấy trong các câu hỏi tôi liên kết

+0

Slick. Như. Heck! Tôi thích rằng định nghĩa chuỗi được nhúng với enum, và bộ chuyển đổi (với một tinh chỉnh nhỏ) là chung cho bất kỳ Enum nào và là duyên dáng mà không có Thuộc tính mô tả. – mbmcavoy

0

Here is a blog post of mine with an approach using attached behaviors.

Nó dựa trên nguyên tắc rằng các giá trị liệt kê khác nhau không cần phải giới hạn trong việc chuyển đổi chuỗi. Thay vào đó, bạn có thể khai báo bất kỳ phần giao diện người dùng nào bạn muốn đại diện cho từng giá trị (chuỗi, hình ảnh, điều khiển và bố cục khác nhau, v.v.) và sử dụng hành vi được đính kèm để kiểm soát khả năng hiển thị của chúng.

Tình huống của bạn, sau đó, có thể được đóng khung là có hai khối văn bản khác nhau, mỗi khối được liên kết với cùng một thuộc tính loại ExportRegulationType. Vì họ đang bị ràng buộc đối với tài sản tương tự, chế độ hiển thị của họ là loại trừ lẫn nhau:

<Grid> 
    <TextBlock 
     Text="EAR" 
     local:EnumVisibility.Value="{Binding ExportRegulationType}" 
     local:EnumVisibility.TargetValue="EAR" 
    /> 
    <TextBlock 
     Text="Do Not Export" 
     local:EnumVisibility.Value="{Binding ExportRegulationType}" 
     local:EnumVisibility.TargetValue="DoNotExport" 
     FontWeight="Bold" 
    /> 
</Grid> 

tôi bao gồm các FontWeight="Bold" để chứng minh rằng bạn có thể đưa ra quyết định khác nhau cho mỗi giá trị liệt kê. Điều này cũng hỗ trợ nội địa hóa XAML vì văn bản được đặt giống như bất kỳ khối văn bản nào khác.

Xem the post để có hướng dẫn đầy đủ về giải pháp, mẫu mã và tệp zip có chứa khung và ứng dụng mẫu.

Chỉnh sửa để đáp ứng thêm thông tin:

Here is another post in the same series which describes how to select enumeration values with Selector controls.

Một ComboBox ràng buộc với ExportRegulationType bất động sản sẽ nhìn này này:

<ComboBox local:EnumSelector.SelectedValue="{Binding ExportRegulationType, Mode=TwoWay}"> 
    <ComboBoxItem Content="EAR" local:EnumSelector.ItemValue="EAR" /> 
    <ComboBoxItem Content="Do Not Export" local:EnumSelector.ItemValue="DoNotExport" /> 
</ComboBox> 

Chúng tôi liên tưởng từng hạng mục với giá trị liệt kê, sau đó sử dụng một liên kết TwoWay để EnumSelector.SelectedValue để nó sẽ ghi lại mô hình xem ' s bất cứ khi nào nó thay đổi.

Điều này cung cấp sự linh hoạt tương tự như với các khối văn bản: bạn có thể thực hiện bất kỳ quyết định nào bạn muốn về cách đặt văn bản và nội dung được chứa bởi từng mục.

+0

Ý tưởng thú vị. Nó không thực sự giải quyết các mối quan tâm trong tầm tay, nhưng tôi có thể thấy nó có thể có ích cho một số tình huống như thế nào. – mbmcavoy

+0

@mbmcavoy: Câu hỏi của bạn được diễn đạt theo một giải pháp được định trước (được gọi là "yêu cầu một người cai trị kim loại mỏng" của Eric Lippert, http://blogs.msdn.com/b/ericlippert/archive/2003/11/03/ a-parable.aspx). Tôi đã xác định và giải quyết vấn đề mà bạn đang cố gắng giải quyết, các tên điều tra thân thiện và kết hợp yêu cầu chính của bạn, không có mô hình trong mô hình xem. Cấp, nó không liên quan đến việc ràng buộc từ điển, nhưng đó không phải là một ràng buộc vốn có của mục tiêu cơ bản của bạn. –

1

Tôi đã giải quyết vấn đề này với sự pha trộn của những gì @Dylan và @Meleak đã viết. Tôi đặt này như là một câu trả lời cho hiển thị những gì là giải pháp cuối cùng là:

Trước tiên, tôi thực hiện một IValueConverter, (dựa trên @ câu trả lời Meleak của):

class EnumDescriptionConverter : IValueConverter 
{ 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     Enum regulation = (Enum)value; 
     return GetEnumDescription(regulation); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return String.Empty; 
    } 

    /// <summary> 
    /// Returns text intended for display based on the Description Attribute of the enumeration value. 
    /// If no Description Attribute is applied, the value is converted to a string and returned. 
    /// </summary> 
    /// <param name="enumObj">The enumeration value to be converted.</param> 
    /// <returns>Text of the Description Attribute or the Enumeration itself converted to string.</returns> 
    private string GetEnumDescription(Enum enumObj) 
    { 
     // Get the DescriptionAttribute of the enum value. 
     FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString()); 
     object[] attributeArray = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); 

     if (attributeArray.Length == 0) 
     { 
      // If no Description Attribute was found, default to enum value conversion. 
      return enumObj.ToString(); 
     } 
     else 
     { 
      // Get the text of the Description Attribute 
      DescriptionAttribute attrib = attributeArray[0] as DescriptionAttribute; 
      return attrib.Description; 
     } 
    } 
} 

tôi gắn thẻ enum của tôi (lưu ý rằng một số giá trị không được gắn thẻ văn bản mong muốn cũng giống như giá trị bản thân):

public enum ExportRegulationType 
{ 
    [Description("Not Determined")] 
    NotDetermined, // Export authority not determined 

    EAR,   // Controlled by EAR Regulations 

    ITAR,   // Controlled by ITAR Regulations 

    [Description("Do Not Export")] 
    DoNotExport, // Export not allowed 

    Unrestricted // Export not controlled 
} 

trong App.xaml tôi, tôi tuyên bố ObjectDataProvider để có được danh sách các giá trị enum và EnumDisplayConverter (Dưới đây vì chúng sẽ được sử dụng bởi một số chế độ xem khác nhau):

<Application.Resources> 
    [Other stuff...] 
    <ObjectDataProvider MethodName="GetValues" 
         ObjectType="{x:Type sys:Enum}" 
         x:Key="ExportRegulationValues"> 
     <ObjectDataProvider.MethodParameters> 
      <x:Type TypeName="models:ExportRegulationType"/> 
     </ObjectDataProvider.MethodParameters>  
    </ObjectDataProvider> 
    <local:EnumDescriptionConverter x:Key="ExportDisplayConverter"/> 
</Application.Resources> 

Đối với một TextBlock:

<TextBlock Text="{Binding Export.Regulation, Converter={StaticResource ExportDisplayConverter}}"/> 

Đối với một combo box:

<ComboBox ItemsSource="{Binding Source={StaticResource ExportRegulationValues}}" 
      SelectedValue="{Binding Document.Export.Regulation}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Converter={StaticResource ExportDisplayConverter}}"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

này hoạt động một cách hoàn hảo !

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