私はクラスを持っています:
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>
私は2つのことをしたいと思います:
DetailsScope
列挙値をコンボボックス値にデータバインドしたいと思います。最後の列挙値はOther detail
ではなくOtherDetail
になるため、列挙値を直接バインドしたくありません(スペース文字と小文字「d」が追加されています)。AccountDetail
オブジェクトのインスタンスで指定した値にデータバインドしたいと思います。手伝ってくれませんか?ありがとう。
更新:この投稿を見つけました http://blogs.msdn.com/b/wpfsdk/archive/2007/02/22/displaying-enum-values-using-data-binding.aspx 。同様のものが必要です。
これを行う非常に簡単な方法は、ObjectDataProviderを使用することです。
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="DetailScopeDataProvider">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:DetailScope" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
ObjectDataProviderをComboBoxのItemsSourceとして使用し、SelectedItemをScopeプロパティにバインドして、各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>
そして、コンバーターでは、 this 質問にあるCamelCase文字列スプリッターにRegexを使用できます。私は最も高度なバージョンを使用しましたが、おそらくよりシンプルなバージョンを使用できます。 OtherDetail + regex =その他の詳細。戻り値を低くして、最初の文字である大文字の文字列を返すと、期待した結果が得られるはずです。
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;
}
}
私がいつもやっているやり方は以下の通りです。このソリューションの優れている点は、完全に汎用的であり、あらゆる列挙型に再利用できることです。
1)列挙を定義するときは、いくつかのカスタム属性を使用して少し情報を提供します。この例では、Browsable(false)を使用して、この列挙子が内部にあることを示しています。このオプションをコンボボックスに表示したくありません。 Description( "")を使用すると、列挙の表示名を指定できます。
public enum MyEnumerationTypeEnum
{
[Browsable(false)]
Undefined,
[Description("Item 1")]
Item1,
[Description("Item 2")]
Item2,
Item3
}
2)EnumerationManagerを呼び出したクラスを定義します。これは、列挙型を分析して値のリストを生成する汎用クラスです。列挙子の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
お役に立てれば。
編集:LocalizableDescriptionAttributeの実装を追加し、代わりにそれを使用する場合、私が使用していたDescription属性は完璧です。
これが解決策です。すべての可能性を含むプロパティ(リスト)を作成し、そのプロパティに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; }
}
これには値コンバーターを使用します。これにより、コンバーターを使用して直接バインドできます。Convertの実装を変更して、列挙型の「より優れた」人間が読める形式にする、つまり大文字で分割することができます。
このアプローチについての完全な記事 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 );
}
}