2009-05-27 7 views
13

अच्छी तरह से समस्या यह है कि मेरे पास यह enum है, लेकिन मैं नहीं चाहता कि combobox enum के मान दिखाए।WPF बाध्यकारी कॉम्बोबॉक्स एनम (एक मोड़ के साथ)

public enum Mode 
    { 
     [Description("Display active only")] 
     Active, 
     [Description("Display selected only")] 
     Selected, 
     [Description("Display active and selected")] 
     ActiveAndSelected 
    } 
ComboBox के बजाय सक्रिय प्रदर्शित करने, चयनित या ActiveAndSelected, मैं enum के प्रत्येक मान के लिए DescriptionProperty प्रदर्शित करना चाहते हैं में

तो: इस enum है।

public static string GetDescription(this Enum enumObj) 
     { 
      FieldInfo fieldInfo = 
       enumObj.GetType().GetField(enumObj.ToString()); 

      object[] attribArray = fieldInfo.GetCustomAttributes(false); 

      if (attribArray.Length == 0) 
      { 
       return enumObj.ToString(); 
      } 
      else 
      { 
       DescriptionAttribute attrib = 
        attribArray[0] as DescriptionAttribute; 
       return attrib.Description; 
      } 
     } 

तो वहाँ एक तरह से मैं ComboBox को enum बाँध और यह GetDescription विस्तार विधि के साथ सामग्री है दिखा सकते हैं: मैं एक विस्तार) enum के लिए GetDescription (बुलाया विधि है?

धन्यवाद!

उत्तर

6

मुझे आपके जैसा लगता है पसंद है। लेकिन GetCustomAttributes प्रतिबिंब का उपयोग करता है। यह आपके प्रदर्शन के लिए क्या करने जा रहा है? इस पोस्ट के बाहर

की जांच: WPF - ComboBox नियंत्रण में प्रदर्शित enums http://www.infosysblogs.com/microsoft/2008/09/wpf_displaying_enums_in_combob.html

+16

Dude, प्रतिबिंब विशेष रूप से समय यह एक जीयूआई प्रदर्शित करने के लिए ले जाता है की तुलना में धीमी गति से _that_ नहीं है,। मैं यह एक समस्या होने की उम्मीद नहीं करता। –

+0

ठीक है, इसके लिए मेरा शब्द न लें। उपरोक्त संदर्भ में कहा गया है कि यह एक चिंता है। –

+3

लेकिन कोई प्रोफ़ाइल परिणाम उद्धृत नहीं करता है। लेखक इसके बारे में चिंतित थे, लेकिन इसका मतलब यह नहीं था कि यह वास्तव में एक समस्या थी। –

3

प्रतिबिंब का उपयोग करने का प्रश्न और अलग गुण, वहाँ कुछ तरीके आप यह कर सकते हैं, लेकिन मुझे लगता है कि सबसे अच्छा तरीका है बस करने के लिए है एक छोटे से दृश्य मॉडल वर्ग कि गणन मूल्य लपेटता बनाएँ:

public class ModeViewModel : ViewModel 
{ 
    private readonly Mode _mode; 

    public ModeViewModel(Mode mode) 
    { 
     ... 
    } 

    public Mode Mode 
    { 
     get { ... } 
    } 

    public string Description 
    { 
     get { return _mode.GetDescription(); } 
    } 
} 

वैकल्पिक रूप से, आप ObjectDataProvider का उपयोग कर इस पर गौर कर सकता है।

3

मैं सुझाव है कि आप सिर्फ एक छोटे संशोधन के साथ एक मार्कअप विस्तार मैं पहले से ही here था का उपयोग करें,:

<ComboBox ItemsSource="{local:EnumValues local:Mode}"/> 

संपादित करें:

[MarkupExtensionReturnType(typeof(IEnumerable))] 
public class EnumValuesExtension : MarkupExtension 
{ 
    public EnumValuesExtension() 
    { 
    } 

    public EnumValuesExtension(Type enumType) 
    { 
     this.EnumType = enumType; 
    } 

    [ConstructorArgument("enumType")] 
    public Type EnumType { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     if (this.EnumType == null) 
      throw new ArgumentException("The enum type is not set"); 
     return Enum.GetValues(this.EnumType).Select(o => GetDescription(o)); 
    } 
} 

फिर आप ऐसा उपयोग कर सकते हैं विधि मैं सुझाव दिया जाएगा स्ट्रिंग की एक सूची से बंधेगा, जो वांछनीय नहीं है क्योंकि हम चयनित इटैम प्रकार मोड के रूप में चाहते हैं। यह चयन करना बेहतर होगा। चयन (...) भाग, और आइटम टेम्पलेट में एक कस्टम कनवर्टर के साथ बाध्यकारी का उपयोग करें।

+0

क्या यह कॉम्बो बॉक्स के चयनित इटैम को मोड के बजाय "केवल सक्रिय प्रदर्शन" नहीं करेगा। सक्रिय? मुझे एक अवांछित दुष्प्रभाव की तरह लगता है। –

+0

तो आप इसका मतलब है कि इस दृष्टिकोण के साथ मैं चयनित आइटम को वर्तमान में चुने गए एनम के साथ ऑब्जेक्ट को सेट करने में सक्षम नहीं होगा? – Carlo

+0

@ जो: हाँ, आप सही हैं ... यह वास्तव में एक समस्या है। मैं अपना उत्तर –

19

मैं डेटा टेम्पलेट और वैल्यू कनवर्टर का सुझाव दूंगा। इससे आपको प्रदर्शित होने के तरीके को कस्टमाइज़ करने दिया जाएगा, लेकिन आप अभी भी कम्बोबॉक्स की चुनीItem प्रॉपर्टी को पढ़ने और वास्तविक एनम मान प्राप्त करने में सक्षम होंगे।

ValueConverters को बहुत सारे बॉयलरप्लेट कोड की आवश्यकता होती है, लेकिन यहां कुछ भी जटिल नहीं है। सबसे पहले आप ValueConverter वर्ग बनाने: चूंकि आप केवल तार (प्रदर्शन के लिए) के लिए enum मान बदल रहे

public class ModeConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, 
     CultureInfo culture) 
    { 
     return ((Mode) value).GetDescription(); 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, 
     CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

, आप ConvertBack जरूरत नहीं है - कि सिर्फ दो तरह से बाध्यकारी परिदृश्यों के लिए है।

तो फिर तुम ValueConverter का एक उदाहरण के लिए अपने संसाधनों में कुछ के साथ इस तरह रखा,: फिर

<Window ... xmlns:WpfApplication1="clr-namespace:WpfApplication1"> 
    <Window.Resources> 
     <WpfApplication1:ModeConverter x:Key="modeConverter"/> 
    </Window.Resources> 
    .... 
</Window> 

आप ComboBox एक DisplayTemplate कि प्रारूप देने के लिए तैयार कर रहे हैं अपने आइटम ModeConverter का उपयोग कर:

<ComboBox Name="comboBox" ...> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Converter={StaticResource modeConverter}}"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

इस परीक्षण के लिए, मैं एक लेबल भी, कि मुझे वास्तविक SelectedItem मूल्य दिखाना चाहते में फेंक दिया, और यह वास्तव में दिखाने की थी कि SelectedItem प्रदर्शन पाठ के बजाय enum है, जो मैं क्या चाहते हो जाएगा है:

<Label Content="{Binding ElementName=comboBox, Path=SelectedItem}"/> 
+0

दोस्त अपडेट करूंगा, आपके उत्तर ने अंततः इंटरनेट खोदने के कुछ घंटों के बाद मेरी समस्या हल कर दी। धन्यवाद! – mcy

6

इस प्रकार मैं इसे एमवीवीएम के साथ कर रहा हूं। अपने मॉडल पर मैं अपने enum परिभाषित होता:

public enum VelocityUnitOfMeasure 
    { 
     [Description("Miles per Hour")] 
     MilesPerHour, 
     [Description("Kilometers per Hour")] 
     KilometersPerHour 
    } 

मेरी ViewModel पर मैं एक संपत्ति है कि स्ट्रिंग के रूप में संभव चयन के साथ ही एक संपत्ति/मॉडल मान सेट करने के लिए प्रदान करता है बेनकाब। यह उपयोगी है अगर हम प्रकार में हर enum मान का उपयोग नहीं करना चाहते हैं: दृश्य के साथ,

public class EnumDescriptionConverter : IValueConverter 
{ 
    //From Binding Source 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (!(value is Enum)) throw new ArgumentException("Value is not an Enum"); 
     return (value as Enum).Description(); 
    } 

    //From Binding Target 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (!(value is string)) throw new ArgumentException("Value is not a string"); 
     foreach(var item in Enum.GetValues(targetType)) 
     { 
      var asString = (item as Enum).Description(); 
      if (asString == (string) value) 
      { 
       return item; 
      } 
     } 
     throw new ArgumentException("Unable to match string to Enum description"); 
    } 
} 

और अंत में मैं कर सकते हैं:

//UI Helper 
    public IEnumerable<string> VelocityUnitOfMeasureSelections 
    { 
     get 
     { 
      var units = new [] 
          { 
           VelocityUnitOfMeasure.MilesPerHour.Description(), 
           VelocityUnitOfMeasure.KilometersPerHour.Description() 
          }; 
      return units; 
     } 
    } 

    //VM property 
    public VelocityUnitOfMeasure UnitOfMeasure 
    { 
     get { return model.UnitOfMeasure; } 
     set { model.UnitOfMeasure = value; } 
    } 

इसके अलावा, मैं एक सामान्य EnumDescriptionCoverter का उपयोग निम्नलिखित:

<Window.Resources> 
    <ValueConverters:EnumDescriptionConverter x:Key="enumDescriptionConverter" /> 
</Window.Resources> 
... 
<ComboBox SelectedItem="{Binding UnitOfMeasure, Converter={StaticResource enumDescriptionConverter}}" 
      ItemsSource="{Binding VelocityUnitOfMeasureSelections, Mode=OneWay}" /> 
+0

Enum.Description() और एक्सटेंशन विधि है? मुझे उस विधि को सिस्टम पर नहीं मिल रहा है। एनीम .. – mtijn

+0

। डिस्क्रिप्शन() एक विस्तार विधि है जो विवरण विशेषता प्राप्त करती है। पिछली दृष्टि में, यह DisplayName विशेषता का उपयोग करने के लिए और अधिक उपयुक्त हो सकता है। –

+0

मैंने प्रश्न निकाय में विस्तार विधि को अनदेखा किया था, जो शायद आप का जिक्र कर रहे थे, और डिस्प्लेनाम का उपयोग नहीं किया जाता है क्योंकि यह enum फ़ील्ड लक्ष्यों पर लागू नहीं होता है (जब तक आप विशेषता का उपयोग नहीं करते) – mtijn

0

मैं इस तरह यह किया है:

<ComboBox x:Name="CurrencyCodeComboBox" Grid.Column="4" DisplayMemberPath="." HorizontalAlignment="Left" Height="22" Margin="11,6.2,0,10.2" VerticalAlignment="Center" Width="81" Grid.Row="1" SelectedValue="{Binding currencyCode}" > 
      <ComboBox.ItemsPanel> 
       <ItemsPanelTemplate> 
        <VirtualizingStackPanel/> 
       </ItemsPanelTemplate> 
      </ComboBox.ItemsPanel> 
     </ComboBox> 

कोड में मैं ItemSource सेट:

CurrencyCodeComboBox.ItemsSource = [Enum].GetValues(GetType(currencyCode))