2010-11-29 157 views
20

我有一個類:WPF數據綁定:如何使用XAML將數據綁定到組合框?

public class AccountDetail 
{ 
    public DetailScope Scope 
    { 
     get { return scope; } 
     set { scope = value; } 
    } 

    public string Value 
    { 
     get { return this.value; } 
     set { this.value = value; } 
    } 

    private DetailScope scope; 
    private string value; 

    public AccountDetail(DetailScope scope, string value) 
    { 
     this.scope = scope; 
     this.value = value; 
    } 
} 

和枚舉:

public enum DetailScope 
{ 
    Private, 
    Business, 
    OtherDetail 
} 

最後,我有一個文件名爲.xaml:

<Window x:Class="Gui.Wpf.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Test" 
    SizeToContent="WidthAndHeight"> 

    <Grid> 
     <ComboBox 
      Name="ScopeComboBox" 
      Width="120" 
      Height="23" 
      Margin="12" /> 
    </Grid> 
</Window> 

我希望做兩件事情:

  1. 我希望數據綁定DetailsScope枚舉值組合框值。我不希望 直接綁定枚舉值,因爲最後一個枚舉值將是OtherDetail而不是 Other detail(添加了空格字符和小寫字母'd')。
  2. 我希望數據綁定組合框中的選定值到AccountDetail對象的 實例中指定的值。

你能幫我嗎?謝謝。

更新:我發現此帖子http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx。我需要類似的東西。

回答

37

一個非常簡單的方法來做到這一點是使用ObjectDataProvider的

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

使用ObjectDataProvider的作爲的ItemsSource組合框,綁定的SelectedItem的作用域屬性和應用用於顯示每個ComboBoxItem的轉換器

<ComboBox Name="ScopeComboBox" 
      ItemsSource="{Binding Source={StaticResource DetailScopeDataProvider}}" 
      SelectedItem="{Binding Scope}" 
      Width="120" 
      Height="23" 
      Margin="12"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Converter={StaticResource CamelCaseConverter}}"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

而在轉換器中,您可以使用Regex for CamelCase string splitter在this問題中找到。我使用了最先進的版本,但您可以使用更簡單的版本。 OtherDetail +正則表達式=其他細節。使返回值較低,然後返回一個字符串與第一個字符UpperCase應該給你預期的結果

public class CamelCaseConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     string enumString = value.ToString(); 
     string camelCaseString = Regex.Replace(enumString, "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))", "$1 ").ToLower(); 
     return char.ToUpper(camelCaseString[0]) + camelCaseString.Substring(1); 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value; 
    } 
} 
2

這裏是一個解決方案:你創建一個包含所有可能性的屬性(一個列表),並將你的ComboBox綁定到該屬性上。

在XAML:

<ComboBox 
    Name="ScopeComboBox" 
    Width="120" 
    Height="23" 
    Margin="12" 
    ItemsSource="{Binding Path=AccountDetailsProperty}" 
    DisplayMemberPath="Value"/> 

而且在後面的代碼:

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     AccountDetailsProperty = new List<AccountDetail>() 
     { 
      new AccountDetail(DetailScope.Business, "Business"), 
      new AccountDetail(DetailScope.OtherDetail, "Other details"), 
      new AccountDetail(DetailScope.Private, "Private"), 
     }; 

     InitializeComponent(); 
     this.DataContext = this; 
    } 

    public List<AccountDetail> AccountDetailsProperty { get; set; } 
} 
+0

尼古拉斯,感謝您的答覆。我正在尋找更多面向XAML的解決方案,例如:http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx – Boris 2010-11-29 18:49:55

11

的方式我一直做了如下。這個解決方案的優點是它是完全通用的,可以重用於任何枚舉類型。

1)當你定義一個枚舉時,利用一些自定義屬性給出一些信息。在這個例子中,我使用了Browsable(false)來表示這個枚舉器是內部的,我不想在組合框中看到這個選項。說明(「」)允許我爲枚舉指定顯示名稱。

public enum MyEnumerationTypeEnum 
    { 
    [Browsable(false)] 
    Undefined, 
    [Description("Item 1")] 
    Item1, 
    [Description("Item 2")] 
    Item2, 
    Item3 
    } 

2)定義一個我稱之爲EnumerationManager的類。這是一個泛型類,用於分析Enumeration類型並生成值列表。如果枚舉器將Browsable設置爲false,則它將被跳過。如果它有一個Description屬性,那麼它將使用描述字符串作爲顯示名稱。如果沒有找到說明,它只會顯示枚舉器的默認字符串。

public class EnumerationManager 
    { 
    public static Array GetValues(Type enumeration) 
    { 
     Array wArray = Enum.GetValues(enumeration); 
     ArrayList wFinalArray = new ArrayList(); 
     foreach(Enum wValue in wArray) 
     { 
     FieldInfo fi = enumeration.GetField(wValue.ToString()); 
     if(null != fi) 
     { 
      BrowsableAttribute[] wBrowsableAttributes = fi.GetCustomAttributes(typeof(BrowsableAttribute),true) as BrowsableAttribute[]; 
      if(wBrowsableAttributes.Length > 0) 
      { 
      // If the Browsable attribute is false 
      if(wBrowsableAttributes[0].Browsable == false) 
      { 
       // Do not add the enumeration to the list. 
       continue; 
      }   
      } 

      DescriptionAttribute[] wDescriptions = fi.GetCustomAttributes(typeof(DescriptionAttribute),true) as DescriptionAttribute[]; 
     if(wDescriptions.Length > 0) 
     { 
     wFinalArray.Add(wDescriptions[0].Description); 
     } 
     else 
     wFinalArray.Add(wValue); 
     } 
     } 

     return wFinalArray.ToArray(); 
    } 
    } 

3)在你的XAML在ResourceDictionary中添加部分

<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type l:EnumerationManager}" x:Key="OutputListForMyComboBox"> 
     <ObjectDataProvider.MethodParameters> 
      <x:Type TypeName="l:MyEnumerationTypeEnum" /> 
     </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 

4)現在只需綁定您的組合框的ItemsSource時,我們剛在資源字典定義此鍵

<ComboBox Name="comboBox2" 
      ItemsSource="{Binding Source={StaticResource OutputListForMyComboBox}}" /> 

如果您使用上面的枚舉嘗試使用此代碼,則應在組合框中看到3個項目:

Item 1 
Item 2 
Item3 

希望這會有所幫助。

EDITS: 如果添加LocalizableDescriptionAttribute的實現並使用它,而不是我使用的Description屬性將是完美的。

+0

Liz,謝謝你的回覆。 – Boris 2010-11-30 00:47:31

+0

這是一個很好的方法。 – gakera 2015-06-08 16:43:56

+0

將SelectedItem綁定回視圖模型的最佳方式是什麼?我試圖直接綁定到視圖模型中的相同類型的枚舉,但它然後獲取描述作爲從控件發送並解析它的字符串(特別是如果本地化)是一種痛苦? – gakera 2015-11-24 13:05:36

0

我會爲此使用一個值轉換器,這將允許您直接使用轉換器進行綁定,您可以更改Convert實現以使enums的「更好」人類可讀展示,即分割大寫字符。

有一篇關於這種方法的完整文章here

public class MyEnumToStringConverter : IValueConverter 
    { 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value.ToString(); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return (MyEnum) Enum.Parse(typeof (MyEnum), value.ToString(), true); 
    } 
    }