WPF में ComboBox के लिए एक एनुम प्रॉपर्टी को डेटाबाइंड करना


256

एक उदाहरण के रूप में निम्नलिखित कोड लेते हैं:

public enum ExampleEnum { FooBar, BarFoo }

public class ExampleClass : INotifyPropertyChanged
{
    private ExampleEnum example;

    public ExampleEnum ExampleProperty 
    { get { return example; } { /* set and notify */; } }
}

मैं एक उदाहरण के लिए एक ComboBox के लिए संपत्तिProProperty Databind करना चाहता हूँ, ताकि यह "FooBar" और "BarFoo" विकल्प दिखाता है और मोड TwoWay में काम करता है। वैकल्पिक रूप से मैं चाहता हूं कि मेरी ComboBox परिभाषा कुछ इस तरह दिखे:

<ComboBox ItemsSource="What goes here?" SelectedItem="{Binding Path=ExampleProperty}" />

वर्तमान में मेरे पास ComboBox.SelectionChanged और ExampleClass.PropertyChanged इवेंट्स हैं जो मेरी विंडो में स्थापित हैं जहाँ मैं बाइंडिंग मैन्युअल रूप से करता हूँ।

क्या कोई बेहतर या किसी तरह का विहित तरीका है? क्या आप आमतौर पर कन्वर्टर्स का उपयोग करेंगे और आप कॉम्बो बॉक्स को सही मानों से कैसे आबाद करेंगे? मैं अभी i18n से शुरुआत नहीं करना चाहता।

संपादित करें

तो एक सवाल का जवाब दिया गया था: मैं कॉम्बो बॉक्स को सही मूल्यों के साथ कैसे पॉपुलेट करता हूं।

स्थिर Enum.GetVigues से ObjectDataProvider के माध्यम से तार की एक सूची के रूप में Enum मानों को प्राप्त करें:

<Window.Resources>
    <ObjectDataProvider MethodName="GetValues"
        ObjectType="{x:Type sys:Enum}"
        x:Key="ExampleEnumValues">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="ExampleEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
</Window.Resources>

यह मैं अपने कॉम्बो बॉक्स के लिए एक आइटम स्रोत के रूप में उपयोग कर सकता हूं:

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

4
मैंने इसे खोजा और इसका एक समाधान है जिसका उपयोग आप यहां स्थित WPF में (स्थानीयकरण के साथ पूरा) कर सकते हैं
उम्रकैद में

जवाबों:


208

आप एक कस्टम मार्कअप एक्सटेंशन बना सकते हैं।

उपयोग का उदाहरण:

enum Status
{
    [Description("Available.")]
    Available,
    [Description("Not here right now.")]
    Away,
    [Description("I don't have time right now.")]
    Busy
}

अपने XAML में सबसे ऊपर:

    xmlns:my="clr-namespace:namespace_to_enumeration_extension_class

और फिर...

<ComboBox 
    ItemsSource="{Binding Source={my:Enumeration {x:Type my:Status}}}" 
    DisplayMemberPath="Description" 
    SelectedValue="{Binding CurrentStatus}"  
    SelectedValuePath="Value"  /> 

और कार्यान्वयन ...

public class EnumerationExtension : MarkupExtension
  {
    private Type _enumType;


    public EnumerationExtension(Type enumType)
    {
      if (enumType == null)
        throw new ArgumentNullException("enumType");

      EnumType = enumType;
    }

    public Type EnumType
    {
      get { return _enumType; }
      private set
      {
        if (_enumType == value)
          return;

        var enumType = Nullable.GetUnderlyingType(value) ?? value;

        if (enumType.IsEnum == false)
          throw new ArgumentException("Type must be an Enum.");

        _enumType = value;
      }
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
      var enumValues = Enum.GetValues(EnumType);

      return (
        from object enumValue in enumValues
        select new EnumerationMember{
          Value = enumValue,
          Description = GetDescription(enumValue)
        }).ToArray();
    }

    private string GetDescription(object enumValue)
    {
      var descriptionAttribute = EnumType
        .GetField(enumValue.ToString())
        .GetCustomAttributes(typeof (DescriptionAttribute), false)
        .FirstOrDefault() as DescriptionAttribute;


      return descriptionAttribute != null
        ? descriptionAttribute.Description
        : enumValue.ToString();
    }

    public class EnumerationMember
    {
      public string Description { get; set; }
      public object Value { get; set; }
    }
  }

7
@Gregor S. मेरा क्या है: गणन है?
जोशुआ

14
@Crown 'my' नाम स्थान उपसर्ग है जिसे आप xaml फ़ाइल के शीर्ष पर घोषित करते हैं: जैसे xmlns: my = "clr-namespace: namespace_to_enumeration_extension_class। Enumeration EnumerationExtension के लिए संक्षिप्त है, xaml में आपको संपूर्ण विस्तार नाम नहीं लिखना है। ।
ग्रिगोर स्लेवेक

33
+1, लेकिन सरलतम चीजों को पूरा करने के लिए WPF द्वारा आवश्यक कोड की मात्रा वास्तव में हेडपिनिंग है
कोनराड मोरावस्की

1
मुझे वास्तव में यह पसंद नहीं है कि यह आपके मॉडल के एक हिस्से के लिए एक संदर्भ का उपयोग करता है - गणना प्रकार - दृश्य में, ItemsSourceपरम में। दृश्य और मॉडल को डिकूप्ड रखने के लिए मुझे दोनों के बीच अनुवाद करने के लिए ViewModel और कोड ViewModel में गणना की एक प्रति बनाने की आवश्यकता होगी ... जो समाधान को सरल और सरल नहीं बनाएगी। या वहाँ ViewModel से ही प्रकार की आपूर्ति करने के लिए एक रास्ता है?
दीपक

6
एक और सीमा यह है कि यदि आप कई भाषाएँ रखते हैं तो आप ऐसा नहीं कर सकते।
रिवर-क्लेयर विलियम्सन

176

दृश्यमॉडल में आप हो सकते हैं:

public MyEnumType SelectedMyEnumType 
{
    get { return _selectedMyEnumType; }
    set { 
            _selectedMyEnumType = value;
            OnPropertyChanged("SelectedMyEnumType");
        }
}

public IEnumerable<MyEnumType> MyEnumTypeValues
{
    get
    {
        return Enum.GetValues(typeof(MyEnumType))
            .Cast<MyEnumType>();
    }
}

XAML में ItemSourceबांधता है MyEnumTypeValuesऔर SelectedItemकरने के लिए SelectedMyEnumType

<ComboBox SelectedItem="{Binding SelectedMyEnumType}" ItemsSource="{Binding MyEnumTypeValues}"></ComboBox>

इसने मेरे यूनिवर्सल ऐप में फ़बाउटली काम किया, और इसे लागू करना बहुत आसान था। धन्यवाद!
नाथन स्ट्रटज़

96

मैं यूआई में एनम के नाम का उपयोग नहीं करना पसंद करता हूं। मैं उपयोगकर्ता के लिए अलग मूल्य ( DisplayMemberPath) और मूल्य के लिए अलग का उपयोग करना पसंद करता हूं (इस मामले में एनम) ( SelectedValuePath)। उन दो मूल्यों को पैक किया जा सकता है KeyValuePairऔर शब्दकोश में संग्रहीत किया जा सकता है ।

XAML

<ComboBox Name="fooBarComboBox" 
          ItemsSource="{Binding Path=ExampleEnumsWithCaptions}" 
          DisplayMemberPath="Value" 
          SelectedValuePath="Key"
          SelectedValue="{Binding Path=ExampleProperty, Mode=TwoWay}" > 

सी#

public Dictionary<ExampleEnum, string> ExampleEnumsWithCaptions { get; } =
    new Dictionary<ExampleEnum, string>()
    {
        {ExampleEnum.FooBar, "Foo Bar"},
        {ExampleEnum.BarFoo, "Reversed Foo Bar"},
        //{ExampleEnum.None, "Hidden in UI"},
    };


private ExampleEnum example;
public ExampleEnum ExampleProperty
{
    get { return example; }
    set { /* set and notify */; }
}

संपादित करें: MVVM पैटर्न के साथ संगत।


14
मुझे लगता है कि आपका उत्तर कमतर है, यह सबसे अच्छा विकल्प लगता है जो कॉम्बो बॉक्स खुद उम्मीद करता है। शायद आप एक डिक्शनरी बिल्डर को पाने वाले में डाल सकते हैं, उपयोग कर सकते हैं Enum.GetValues, लेकिन वह नामों के भाग को प्रदर्शित नहीं करेगा। अंत में, और विशेष रूप से अगर I18n को लागू किया जाता है, तो आपको मैन्युअल रूप से सामान बदलना होगा यदि एनुम बदलता है, वैसे भी। लेकिन एनमों को अक्सर बदलने की ज़रूरत नहीं है, यदि वे बिल्कुल हैं? +1
हेल्टनबिकर

2
यह उत्तर बहुत ही बढ़िया है और यह enums विवरण को स्थानीय बनाने की अनुमति देता है ... इसके लिए धन्यवाद!
शाय

2
यह समाधान बहुत अच्छा है क्योंकि यह अन्य समाधानों की तुलना में कम कोड के साथ एनम और स्थानीयकरण दोनों को संभालता है!
hfann

2
शब्दकोश के साथ समस्या यह है कि चाबियाँ हैश मूल्य द्वारा आदेशित की जाती हैं, इसलिए उस पर थोड़ा नियंत्रण होता है। हालांकि थोड़ी अधिक क्रिया, मैंने इसके बजाय List <KeyValuePair <enum, string >> का उपयोग किया। अछा सुझाव।
केविन ब्रॉक

3
@CoperNick @Pragmateek नया फिक्स:public Dictionary<ExampleEnum, string> ExampleEnumsWithCaptions { get; } = new Dictionary<ExampleEnum, string>() { {ExampleEnum.FooBar, "Foo Bar"}, {ExampleEnum.BarFoo, "Reversed Foo Bar"}, //{ExampleEnum.None, "Hidden in UI"}, };
जिनजिनोव

40

मुझे नहीं पता कि यह XAML में ही संभव है लेकिन केवल निम्नलिखित प्रयास करें:

अपने कॉम्बो बॉक्स को एक नाम दें ताकि आप इसे कोडबेहिन्द में एक्सेस कर सकें: "टाइप.कॉमबबॉक्स 1"

अब निम्नलिखित प्रयास करें

typesComboBox1.ItemsSource = Enum.GetValues(typeof(ExampleEnum));

24

स्वीकार किए गए लेकिन अब हटाए गए आयु- उत्तर द्वारा प्रदान किए गए उत्तर के आधार पर मैंने कुछ अधिक उन्नत सुविधाओं के बिना एक पतला डाउन संस्करण बनाया। आपको इसे कॉपी-पेस्ट करने और लिंक-रोट द्वारा अवरुद्ध न होने देने के लिए सभी कोड यहां शामिल हैं।

मैं System.ComponentModel.DescriptionAttributeडिजाइन समय विवरणों के लिए वास्तव में अभिप्रेत है। यदि आप इस विशेषता का उपयोग करना पसंद करते हैं, तो आप अपना स्वयं का निर्माण कर सकते हैं, लेकिन मुझे लगता है कि इस विशेषता का उपयोग करने से वास्तव में काम हो जाता है। यदि आप विशेषता का उपयोग नहीं करते हैं तो नाम कोड में एनम मान के नाम के लिए डिफ़ॉल्ट होगा।

public enum ExampleEnum {

  [Description("Foo Bar")]
  FooBar,

  [Description("Bar Foo")]
  BarFoo

}

यहाँ आइटम स्रोत के रूप में उपयोग की जाने वाली कक्षा है:

public class EnumItemsSource : Collection<String>, IValueConverter {

  Type type;

  IDictionary<Object, Object> valueToNameMap;

  IDictionary<Object, Object> nameToValueMap;

  public Type Type {
    get { return this.type; }
    set {
      if (!value.IsEnum)
        throw new ArgumentException("Type is not an enum.", "value");
      this.type = value;
      Initialize();
    }
  }

  public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture) {
    return this.valueToNameMap[value];
  }

  public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture) {
    return this.nameToValueMap[value];
  }

  void Initialize() {
    this.valueToNameMap = this.type
      .GetFields(BindingFlags.Static | BindingFlags.Public)
      .ToDictionary(fi => fi.GetValue(null), GetDescription);
    this.nameToValueMap = this.valueToNameMap
      .ToDictionary(kvp => kvp.Value, kvp => kvp.Key);
    Clear();
    foreach (String name in this.nameToValueMap.Keys)
      Add(name);
  }

  static Object GetDescription(FieldInfo fieldInfo) {
    var descriptionAttribute =
      (DescriptionAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(DescriptionAttribute));
    return descriptionAttribute != null ? descriptionAttribute.Description : fieldInfo.Name;
  }

}

आप इसे इस तरह XAML में उपयोग कर सकते हैं:

<Windows.Resources>
  <local:EnumItemsSource
    x:Key="ExampleEnumItemsSource"
    Type="{x:Type local:ExampleEnum}"/>
</Windows.Resources>
<ComboBox
  ItemsSource="{StaticResource ExampleEnumItemsSource}"
  SelectedValue="{Binding ExampleProperty, Converter={StaticResource ExampleEnumItemsSource}}"/> 

23

ObjectDataProvider का उपयोग करें:

<ObjectDataProvider x:Key="enumValues"
   MethodName="GetValues" ObjectType="{x:Type System:Enum}">
      <ObjectDataProvider.MethodParameters>
           <x:Type TypeName="local:ExampleEnum"/>
      </ObjectDataProvider.MethodParameters>
 </ObjectDataProvider>

और फिर स्थिर संसाधन से बंधे:

ItemsSource="{Binding Source={StaticResource enumValues}}"

इस ब्लॉग पर इसका समाधान खोजें


अच्छा उत्तर। संयोग से, यह आपको Converterएनम-टू-स्ट्रिंग समस्या के लिए चिंता करने से बचाता है ।
डॉनबॉइटनोट

1
लिंक्ड सॉल्यूशन मृत (कोरियाई या जापानी पाठ?) लगता है। अगर मैं अपना कोड अपने XAML रिसोर्स में डालता हूं तो यह कहता है कि Enum एक WPF प्रोजेक्ट में समर्थित नहीं है।
सेबस्टियन

6

ऐसा करने का मेरा पसंदीदा तरीका है ValueConverterताकि आइटम्ससोर्स और सिलेक्टवैल्यू दोनों एक ही प्रॉपर्टी से जुड़ जाएं। यह आपके ViewModel को अच्छा और साफ रखने के लिए अतिरिक्त गुणों की आवश्यकता नहीं है

<ComboBox ItemsSource="{Binding Path=ExampleProperty, Converter={x:EnumToCollectionConverter}, Mode=OneTime}"
          SelectedValuePath="Value"
          DisplayMemberPath="Description"
          SelectedValue="{Binding Path=ExampleProperty}" />

और कन्वर्टर की परिभाषा:

public static class EnumHelper
{
  public static string Description(this Enum e)
  {
    return (e.GetType()
             .GetField(e.ToString())
             .GetCustomAttributes(typeof(DescriptionAttribute), false)
             .FirstOrDefault() as DescriptionAttribute)?.Description ?? e.ToString();
  }
}

[ValueConversion(typeof(Enum), typeof(IEnumerable<ValueDescription>))]
public class EnumToCollectionConverter : MarkupExtension, IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return Enum.GetValues(value.GetType())
               .Cast<Enum>()
               .Select(e => new ValueDescription() { Value = e, Description = e.Description()})
               .ToList();
  }
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return null;
  }
  public override object ProvideValue(IServiceProvider serviceProvider)
  {
    return this;
  }
}

यह कन्वर्टर किसी भी एनम के साथ काम करेगा। ValueDescriptionएक Valueसंपत्ति और एक Descriptionसंपत्ति के साथ सिर्फ एक साधारण वर्ग है । तुम बस के रूप में आसानी से एक इस्तेमाल कर सकते हैं Tupleके साथ Item1और Item2या, एक KeyValuePairसाथ Keyऔर Valueबजाय मूल्य का और विवरण या लंबे समय यह एक enum मूल्य और कहा कि enum मूल्य की स्ट्रिंग वर्णन पकड़ सकता है के रूप में के रूप में अपनी पसंद के किसी भी अन्य वर्ग।


अच्छा उत्तर! के लिए ValueDescriptionवर्ग, Descriptionसंपत्ति अगर जरूरत नहीं छोड़ा जा सकता है। केवल Valueसंपत्ति के साथ एक साधारण वर्ग भी काम करता है!
पोगोस्मा

इसके अलावा, यदि आप एक रेडियोबटन को बांधना चाहते हैं, तो कन्वर्ट विधि को क्लास .Select(e => e.ToString())का उपयोग करने के बजाय , यानी , तार की एक सूची वापस करना होगा ValueDescription
पोगोसम

इसके बजाय ValueDescriptionभी KeyValuePairइस्तेमाल किया जा सकता है, जैसे यहाँ दिखाया गया है
Apfelkuacha

5

यहाँ एक सहायक विधि का उपयोग कर एक सामान्य समाधान है। यह किसी भी अंतर्निहित प्रकार (बाइट, सोबेट, यूंट, लॉन्ग, इत्यादि) का एनुम भी संभाल सकता है।

सहायक विधि:

static IEnumerable<object> GetEnum<T>() {
    var type    = typeof(T);
    var names   = Enum.GetNames(type);
    var values  = Enum.GetValues(type);
    var pairs   =
        Enumerable.Range(0, names.Length)
        .Select(i => new {
                Name    = names.GetValue(i)
            ,   Value   = values.GetValue(i) })
        .OrderBy(pair => pair.Name);
    return pairs;
}//method

मॉडल देखें:

public IEnumerable<object> EnumSearchTypes {
    get {
        return GetEnum<SearchTypes>();
    }
}//property

सम्मिश्रण पटी:

<ComboBox
    SelectedValue       ="{Binding SearchType}"
    ItemsSource         ="{Binding EnumSearchTypes}"
    DisplayMemberPath   ="Name"
    SelectedValuePath   ="Value"
/>

5

आप कुछ इस तरह से विचार कर सकते हैं:

  1. टेक्स्टब्लॉक या किसी अन्य नियंत्रण के लिए एक शैली परिभाषित करें जिसका उपयोग आप अपनी एनम को प्रदर्शित करने के लिए करना चाहते हैं:

    <Style x:Key="enumStyle" TargetType="{x:Type TextBlock}">
        <Setter Property="Text" Value="&lt;NULL&gt;"/>
        <Style.Triggers>
            <Trigger Property="Tag">
                <Trigger.Value>
                    <proj:YourEnum>Value1<proj:YourEnum>
                </Trigger.Value>
                <Setter Property="Text" Value="{DynamicResource yourFriendlyValue1}"/>
            </Trigger>
            <!-- add more triggers here to reflect your enum -->
        </Style.Triggers>
    </Style>
  2. ComboBoxItem के लिए अपनी शैली को परिभाषित करें

    <Style TargetType="{x:Type ComboBoxItem}">
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <TextBlock Tag="{Binding}" Style="{StaticResource enumStyle}"/>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
  3. एक कॉम्बोक्स जोड़ें और इसे अपने एनम मूल्यों के साथ लोड करें:

    <ComboBox SelectedValue="{Binding Path=your property goes here}" SelectedValuePath="Content">
        <ComboBox.Items>
            <ComboBoxItem>
                <proj:YourEnum>Value1</proj:YourEnum>
            </ComboBoxItem>
        </ComboBox.Items>
    </ComboBox>

यदि आपकी एनुम बड़ी है, तो आप निश्चित रूप से कोड में एक ही कर सकते हैं, बहुत टाइपिंग को बख्शते हुए। मुझे वह दृष्टिकोण पसंद है, क्योंकि यह स्थानीयकरण को आसान बनाता है - आप एक बार सभी टेम्पलेट्स को परिभाषित करते हैं, और फिर, आप केवल अपनी स्ट्रिंग संसाधन फ़ाइलों को अपडेट करते हैं।


चयनितValuePath = "सामग्री" ने मुझे यहाँ मदद की। मेरे पास स्ट्रिंग मूल्यों के रूप में मेरा कॉम्बो बॉक्स इट्स है, और रखा जा रहा है और कॉम्बो बॉक्स इट को मेरे एनम प्रकार में परिवर्तित नहीं कर सकता है। धन्यवाद
adriaanp

2

यदि आप एमवीवीएम का उपयोग कर रहे हैं, तो @rudigrobler जवाब के आधार पर आप निम्नलिखित कार्य कर सकते हैं:

निम्न संपत्ति को ViewModel वर्ग में जोड़ें

public Array ExampleEnumValues => Enum.GetValues(typeof(ExampleEnum));

फिर XAML में निम्नलिखित कार्य करें:

<ComboBox ItemsSource="{Binding ExampleEnumValues}" ... />

1

यह एक DevExpressविशिष्ट उत्तर है, Gregor S.(वर्तमान में इसमें 128 मत हैं) शीर्ष मत पर दिए गए उत्तर के आधार पर ।

इसका मतलब है कि हम स्टाइल को पूरे एप्लिकेशन के अनुरूप रख सकते हैं:

यहां छवि विवरण दर्ज करें

दुर्भाग्य से, मूल उत्तर के साथ काम नहीं करता है ComboBoxEdit देवएक्सप्रेस से कुछ संशोधनों के बिना ।

सबसे पहले, के लिए XAML ComboBoxEdit:

<dxe:ComboBoxEdit ItemsSource="{Binding Source={xamlExtensions:XamlExtensionEnumDropdown {x:myEnum:EnumFilter}}}"
    SelectedItem="{Binding BrokerOrderBookingFilterSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
    DisplayMember="Description"
    MinWidth="144" Margin="5" 
    HorizontalAlignment="Left"
    IsTextEditable="False"
    ValidateOnTextInput="False"
    AutoComplete="False"
    IncrementalFiltering="True"
    FilterCondition="Like"
    ImmediatePopup="True"/>

कहने की जरूरत नहीं है, आपको xamlExtensionsउन नामस्थान पर इंगित करना होगा, जिसमें XAML एक्सटेंशन क्लास (जो नीचे परिभाषित है):

xmlns:xamlExtensions="clr-namespace:XamlExtensions"

और हमें myEnumउन नामस्थानों की ओर संकेत करना होगा , जिनमें एनम है:

xmlns:myEnum="clr-namespace:MyNamespace"

फिर, एनम:

namespace MyNamespace
{
    public enum EnumFilter
    {
        [Description("Free as a bird")]
        Free = 0,

        [Description("I'm Somewhat Busy")]
        SomewhatBusy = 1,

        [Description("I'm Really Busy")]
        ReallyBusy = 2
    }
}

एक्सएएमएल के साथ समस्या यह है कि हम इसका उपयोग नहीं कर सकते हैं SelectedItemValue, क्योंकि यह एक त्रुटि फेंकता है क्योंकि सेटर अस्वीकार्य है (आपके हिस्से पर एक नज़र का थोड़ा सा DevExpress)। इसलिए हमें अपने ViewModelऑब्जेक्ट से सीधे मूल्य प्राप्त करने के लिए संशोधित करना होगा:

private EnumFilter _filterSelected = EnumFilter.All;
public object FilterSelected
{
    get
    {
        return (EnumFilter)_filterSelected;
    }
    set
    {
        var x = (XamlExtensionEnumDropdown.EnumerationMember)value;
        if (x != null)
        {
            _filterSelected = (EnumFilter)x.Value;
        }
        OnPropertyChanged("FilterSelected");
    }
}

पूर्णता के लिए, यहां मूल उत्तर (थोड़ा नाम बदला) से XAML एक्सटेंशन है:

namespace XamlExtensions
{
    /// <summary>
    ///     Intent: XAML markup extension to add support for enums into any dropdown box, see http://bit.ly/1g70oJy. We can name the items in the
    ///     dropdown box by using the [Description] attribute on the enum values.
    /// </summary>
    public class XamlExtensionEnumDropdown : MarkupExtension
    {
        private Type _enumType;


        public XamlExtensionEnumDropdown(Type enumType)
        {
            if (enumType == null)
            {
                throw new ArgumentNullException("enumType");
            }

            EnumType = enumType;
        }

        public Type EnumType
        {
            get { return _enumType; }
            private set
            {
                if (_enumType == value)
                {
                    return;
                }

                var enumType = Nullable.GetUnderlyingType(value) ?? value;

                if (enumType.IsEnum == false)
                {
                    throw new ArgumentException("Type must be an Enum.");
                }

                _enumType = value;
            }
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            var enumValues = Enum.GetValues(EnumType);

            return (
                from object enumValue in enumValues
                select new EnumerationMember
                       {
                           Value = enumValue,
                           Description = GetDescription(enumValue)
                       }).ToArray();
        }

        private string GetDescription(object enumValue)
        {
            var descriptionAttribute = EnumType
                .GetField(enumValue.ToString())
                .GetCustomAttributes(typeof (DescriptionAttribute), false)
                .FirstOrDefault() as DescriptionAttribute;


            return descriptionAttribute != null
                ? descriptionAttribute.Description
                : enumValue.ToString();
        }

        #region Nested type: EnumerationMember
        public class EnumerationMember
        {
            public string Description { get; set; }
            public object Value { get; set; }
        }
        #endregion
    }
}

डिस्क्लेमर: मेरा DevExpress से कोई जुड़ाव नहीं है। Telerik भी एक महान पुस्तकालय है।


रिकॉर्ड के लिए, मैं DevExpress से संबद्ध नहीं हूं। Telerik में बहुत ही अच्छी लाइब्रेरियाँ हैं, और यह तकनीक उनके पुस्तकालय के लिए आवश्यक भी नहीं हो सकती है।
कंटैंगो

0

प्रयोग करके देखें

<ComboBox ItemsSource="{Binding Source={StaticResource ExampleEnumValues}}"
    SelectedValue="{Binding Path=ExampleProperty}" />

यह काम नहीं करता है। कॉम्बोक्स बस एक खाली पाठ दिखाएगा और इसे बदलने से कुछ भी नहीं होगा। मुझे लगता है कि यहां एक कनवर्टर में फेंकना सबसे अच्छा समाधान होगा।
मैक्सिमिलियन

0

मैंने एक ओपन सोर्स कोडप्लेक्स प्रोजेक्ट बनाया है जो ऐसा करता है। आप यहां से NuGet पैकेज डाउनलोड कर सकते हैं

<enumComboBox:EnumComboBox EnumType="{x:Type demoApplication:Status}" SelectedValue="{Binding Status}" />
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.