2011-08-26 68 views
5

我有一個枚舉屬性的模型(在這種情況下,與出口管制條例有關)。向用戶顯示值時,我想顯示相應的字符串。有時這是在ComboBox中(用戶可以選擇一個值),有時它在TextBlock中(它是隻讀的)。將textblock綁定到XAML中的鍵的字典值?

例如:對於ExportRegulationType.EAR,我想顯示"EAR",而對於ExportRegulationType.DoNotExport,我想顯示"Do Not Export"。請注意,我沒有任何語言本地化的需求,但我認識到這個問題...

目前,在我的ViewModel,我有一個屬性返回一個字符串基於當前的枚舉值,還有另一個屬性返回Dictionary<ExportRegulationType, string>。對於組合框,我可以將ItemsSource綁定到字典屬性,對於TextBlocks,我可以綁定到字符串屬性。這有效,但有點笨拙。

兩個問題:

1)在我看來,我應該能夠申報詞典(與鍵和值),如XAML(可能在App.xaml中)的靜態資源,並利用它來進行ComboBox版本的ItemsSource。但是,我無法弄清楚如何聲明和引用這樣的事情。我怎樣才能做到這一點?

2)假設上面已經存在,我想我也可以設置與textblock的綁定,所以根據enum屬性,它會查找字典中的字符串。

我看到以下有關staticdynamic枚舉值的問題。首先是不夠的,第二個是沒有回答......

這應該是一個XAML只,並將使我刪除從我的ViewModel(只具有一個暴露ExportRegulationType所列財產的方法。這些是可能的

編輯:附加信息:

在應用程序中,我將有很多套不同的意見,模型和的ViewModels然而,由於出口控制法規是共同一致的要求,我正在使用合成來保持它乾燥,即模型A和B都有一個ExportControl模型,ViewModels A1,A2,B1和B2將ha有一個ExportControlViewModel。視圖將具有綁定到其ViewModel的ExportControlViewModel的控件。視圖將有一個ComboBox或一個TextBlock,但不能同時使用(取決於用戶是否可以更改該值)。

+0

添加了C#作爲標籤,所以答案得到語法突出顯示 –

回答

3

我不知道這是否適用於您的情況,但這裏有一個可能的解決方案。在您的視圖模型中,公開一個ExportRegulationType屬性,然後創建一個value converter以顯示所需的字符串。

首先創建您的值轉換器:

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 
} 

然後在你的XAML添加到轉換器的參考。 本地是你的類所在的命名空間。

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

最後,將文本框的值設置爲使用轉換器。 pathToEnum是暴露在您的ViewModel類型ExportRegulationType上的屬性。

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

使用ObjectDataProvider來使用enum的值填充ComboBox。

<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> 

現在我們創建一個組合框,並使用一個容器的風格與我們value converter以顯示我們的枚舉所需的字符串。

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

我希望我可以選擇兩個答案;我正在給你正確的方向迅速的信貸,並需要更多的代表! – mbmcavoy

+0

哦,注意:使用ComboBox.ItemContainerStyle幾乎可以工作 - 下拉列表中的項目是正確的。但是,選擇某個項目並關閉下拉列表時,會顯示enum.ToString()值。使用數據模板而不是正常工作。 – mbmcavoy

1

使用ObjectDataProvider 然後綁定組合框的項目給它,並設置「的DisplayMemberPath」到「值」。

這個應該做的是顯示你的字典的值,但在代碼後面的SelectedValueKeyValuePair<>

爲了您的文字塊,使用Binding使用ElementName=yourcomboboxPath=SelectedItem

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

讓我知道如何去=)

2

取而代之的Dictionary你有另一種選擇。

請參見下面的問題:WPF Binding a ListBox to an enum, displaying the Description Attribute

你可以一個Description屬性添加到您的枚舉這樣

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

而當你想要顯示它,你可以只使用EnumDescriptionConverter轉換器中的問題找到我鏈接

+0

油滑。如。哎呀!我喜歡將字符串定義嵌入到枚舉中,並且轉換器(稍作調整)對於任何枚舉都是通用的,並且沒有描述屬性就是優雅的。 – mbmcavoy

0

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

它基於原則是不同枚舉值不需要限制切換字符串。相反,您可以聲明您想要表示每個值的任何部分(字符串,圖像,不同的控件和佈局等),並使用附加的行爲來控制其可見性。

然後,您的情況可以被定義爲具有兩個不同的文本塊,每個文本塊都綁定到ExportRegulationType類型的相同屬性。由於他們被綁定到相同的屬性,它們的可見性是相互排斥的:

<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> 

我包括FontWeight="Bold",說明你可以爲每個枚舉值做出不同的決定。這也支持XAML本地化,因爲文本像任何其他文本塊一樣設置。

請參閱the post瞭解解決方案,代碼示例以及包含框架和示例應用程序的zip文件的完整演練。

編輯迴應附加信息:

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

綁定到ExportRegulationType屬性的ComboBox看起來這本:

<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> 

我們每個項目有一個枚舉值相關聯,然後使用TwoWay綁定到EnumSelector.SelectedValue,以便它將回寫到視圖模型'只要它發生變化,它的財產。

這提供了與文本塊相同的靈活性:您可以對如何設置文本以及每個項目包含的內容做出任何決定。

+0

有趣的想法。它並沒有真正解決手頭的顧慮,但我可以看到它在某些情況下如何派上用場。 – mbmcavoy

+0

@mbmcavoy:您的問題是根據預先設定的解決方案(被Eric Lippert稱爲「要求薄金屬標尺」,http://blogs.msdn.com/b/ericlippert/archive/2003/11/03/一個-parable.aspx)。我確定並解決了您正在嘗試解決的問題,友好的枚舉名稱,並納入了您的主要要求,在視圖模型中沒有殘留。當然,它不涉及字典綁定,但這不是您的基本目標的固有限制。 –

1

我用@Dylan和@Meleak寫的東西來解決這個問題。我把這個作爲一個答案顯示什麼最終的解決方案是:

首先,我實現了一個的IValueConverter,(根據@ Meleak的答案):

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; 
     } 
    } 
} 

我標記我的枚舉(注意幾個值不標記爲所需的文本是一樣的本身的價值):

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 
} 

在我的App.xaml,我宣佈的ObjectDataProvider獲得枚舉值的列表和EnumDisplayConverter(在這裏,因爲他們將是由幾個不同的意見使用):

<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> 

TextBlock的:

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

組合框:

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

這工作完美

相關問題