RadioButtons को एक Enum में कैसे बांधें?


406

मुझे इस तरह एक एनम मिला है:

public enum MyLovelyEnum
{
    FirstSelection,
    TheOtherSelection,
    YetAnotherOne
};

मुझे अपने DataContext में एक संपत्ति मिली:

public MyLovelyEnum VeryLovelyEnum { get; set; }

और मुझे अपने WPF क्लाइंट में तीन RadioButtons मिले।

<RadioButton Margin="3">First Selection</RadioButton>
<RadioButton Margin="3">The Other Selection</RadioButton>
<RadioButton Margin="3">Yet Another one</RadioButton>

अब मैं एक उचित टू-वे बाइंडिंग के लिए रेडियोबटन को संपत्ति में कैसे बाँधूं?


3
यदि आप अपने XAML में अलग-अलग RadioButtons को निर्दिष्ट किए बिना ऐसा करना चाह रहे हैं, तो मैं इस या इस तरह के एनम मूल्यों के लिए बाध्य एक ListBox की सिफारिश करूंगा , और इस तरह से RadioButtons का उपयोग करने के लिए आइटम टेम्पलेट ओवरराइट किया गया है ।
राहेल

जवाबों:


389

आप एक अधिक सामान्य कनवर्टर का उपयोग कर सकते हैं

public class EnumBooleanConverter : IValueConverter
{
  #region IValueConverter Members
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    string parameterString = parameter as string;
    if (parameterString == null)
      return DependencyProperty.UnsetValue;

    if (Enum.IsDefined(value.GetType(), value) == false)
      return DependencyProperty.UnsetValue;

    object parameterValue = Enum.Parse(value.GetType(), parameterString);

    return parameterValue.Equals(value);
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    string parameterString = parameter as string;
    if (parameterString == null)
        return DependencyProperty.UnsetValue;

    return Enum.Parse(targetType, parameterString);
  }
  #endregion
}

और आपके द्वारा उपयोग किए जाने वाले XAML- भाग में:

<Grid>
    <Grid.Resources>
      <l:EnumBooleanConverter x:Key="enumBooleanConverter" />
    </Grid.Resources>
    <StackPanel >
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=FirstSelection}">first selection</RadioButton>
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=TheOtherSelection}">the other selection</RadioButton>
      <RadioButton IsChecked="{Binding Path=VeryLovelyEnum, Converter={StaticResource enumBooleanConverter}, ConverterParameter=YetAnotherOne}">yet another one</RadioButton>
    </StackPanel>
</Grid>

51
मेरे लिए एक जादू की तरह काम किया। इसके अलावा मैंने ConvertBack को "झूठे" पर UnsetValue भी लौटाया, क्योंकि सिल्वरलाइट (और संभवतः WPF उचित) कनवर्टर को दो बार कॉल करता है - एक बार जब पुराने रेडियो बटन मूल्य को परेशान करते हैं और फिर से नया सेट करने के लिए। मैं प्रॉपर्टी सेटर से अन्य चीजें लटका रहा था इसलिए मैं केवल एक बार फोन करना चाहता था। - अगर (पैरामीटरस्ट्रिंग == null || value.Equals (false)) DependencyProperty.UnsetValue वापस करें;
मार्क

8
जब तक मैं बता सकता हूं, यह तब तक किया जाना चाहिए जब तक कि रेडियो बटन अलग-अलग समूहों में न हों (और समूह नाम के बिना AFAIK बटन, जिनके समान माता-पिता एक ही समूह में डिफ़ॉल्ट रूप से हैं)। अन्यथा, संपत्ति को "उछाल" सेट करने और अजीब व्यवहार के परिणामस्वरूप कॉल किया जाता है।
मुलवल्कर

2
हां, लेकिन यदि आप गलत पर सेट करते समय कनवर्टर में Unset कहते हैं, तो यह एक सच्चा EnumToBooleanConverter नहीं है, बल्कि एक EnumToRadioButtonConverter है। इसलिए इसके बजाय मैं जांचता हूं कि मेरे प्रॉपर्टी सेटर में वैल्यू अलग है या नहीं: अगर (_myEnumBackingField == वैल्यू) रिटर्न;
स्टीफन

8
इस समाधान पर बाध्यकारी केवल सही तरीके से काम करता है। मैं प्रोग्रामबिलिटी को एक अलग मान से बाइंड की गई संपत्ति को असाइन करके रेडियोबूटन को टॉगल नहीं कर सकता था। यदि आप एक उचित कार्य और बेहतर समाधान चाहते हैं, तो स्कॉट के दृष्टिकोण का उपयोग करें।
l46kok

2
@Marc, 'Binding.DoNothing' और 'DependencyProperty.UnsetValue' नहीं है कि मामले में वापस जाने के लिए उचित बात नहीं है?
मार्क ए। डोनोहे

559

आप स्वीकृत उत्तर को और सरल कर सकते हैं। एनाम में स्ट्रिंग के रूप में टाइप करने और जरूरत से ज्यादा अपने कनवर्टर में काम करने के बजाय, आप स्पष्ट रूप से एक स्ट्रिंग प्रतिनिधित्व के बजाय एनम मूल्य में पास कर सकते हैं, और जैसा कि क्रिमसनएक्स ने टिप्पणी की, त्रुटियों को रनटाइम की तुलना में संकलन समय पर फेंक दिया जाता है:

कन्वर्टरपेयर = {x: स्टेटिक लोकल: YourEnumType.Enum1}

<StackPanel>
    <StackPanel.Resources>          
        <local:ComparisonConverter x:Key="ComparisonConverter" />          
    </StackPanel.Resources>
    <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:YourEnumType.Enum1}}" />
    <RadioButton IsChecked="{Binding Path=YourEnumProperty, Converter={StaticResource ComparisonConverter}, ConverterParameter={x:Static local:YourEnumType.Enum2}}" />
</StackPanel>

फिर कनवर्टर को सरल बनाएं:

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

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value?.Equals(true) == true ? parameter : Binding.DoNothing;
    }
}

संपादित करें (16 दिसंबर 10):

बाइंडिंग को वापस भेजने के सुझाव के लिए एनॉन का धन्यवाद।


नोट - एक ही कंटेनर में रेडियोबटन के कई समूह (17 फ़रवरी 11):

Xaml में, यदि रेडियो बटन एक ही मूल कंटेनर को साझा करते हैं, तो एक का चयन उस कंटेनर के भीतर अन्य सभी का चयन करेगा (भले ही वे एक अलग संपत्ति से बंधे हों)। तो अपने RadioButton को रखने की कोशिश करें जो एक समान संपत्ति के साथ बंधे हों जैसे कि अपने स्वयं के कंटेनर में एक स्टैक पैनल की तरह। ऐसे मामलों में जहां आपके संबंधित रेडियोबटन एक भी माता-पिता कंटेनर को साझा नहीं कर सकते हैं, फिर प्रत्येक रेडियोबटन के GroupName गुण को सामान्य रूप से उन्हें समूहबद्ध करने के लिए एक सामान्य मान सेट करें।


संपादित करें (अप्रैल 5 '11):

सरलीकृत ConvertBack का यदि और नहीं तो एक Ternary ऑपरेटर का उपयोग करने के लिए।


नोट - एनम प्रकार एक वर्ग में निहित है (अप्रैल 28 '11):

यदि आपकी ईनम का प्रकार एक वर्ग (सीधे नामस्थान में) में नेस्टेड है, तो आप XAML में एनम तक पहुँचने के लिए '+' सिंटैक्स का उपयोग करने में सक्षम हो सकते हैं (जैसा कि चिह्नित नहीं है) प्रश्न का उत्तर खोजने में असमर्थ है। WPF में स्थिर संदर्भ के लिए enum प्रकार :

कन्वर्टरपेयर = {x: स्टेटिक लोकल: YourClass + YourNestedEnumType.Enum1}

इस Microsoft कनेक्ट इश्यू के कारण , हालांकि, VS2010 में डिज़ाइनर अब स्टिंग को लोड नहीं करेगा "Type 'local:YourClass+YourNestedEnumType' was not found.", लेकिन प्रोजेक्ट कंपाइल करता है और सफलतापूर्वक चलता है। बेशक, आप इस समस्या से बच सकते हैं यदि आप अपने एनम प्रकार को सीधे नामस्थान पर ले जाने में सक्षम हैं।


संपादित करें (27 जनवरी 12):

यदि Enum झंडे का उपयोग करते हैं, तो कनवर्टर निम्नानुसार होगा:

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

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value.Equals(true) ? parameter : Binding.DoNothing;
    }
}

संपादित करें (7 मई 15):

एक अशक्त एनम के मामले में (जो प्रश्न में नहीं पूछा गया है, लेकिन कुछ मामलों में इसकी आवश्यकता हो सकती है, जैसे ORM DB से DB लौट रहा है या जब भी यह समझ सकता है कि प्रोग्राम लॉजिक में मान प्रदान नहीं किया गया है), जोड़ना याद रखें कन्वर्ट विधि में एक प्रारंभिक अशक्त जाँच करें और उचित बूल मान लौटाएँ, जो आम तौर पर गलत है (यदि आप किसी भी रेडियो बटन का चयन नहीं करना चाहते हैं), नीचे की तरह:

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null) {
            return false; // or return parameter.Equals(YourEnumType.SomeDefaultValue);
        }
        return value.Equals(parameter);
    }

नोट - NullReferenceException (10 अक्टूबर 18):

NullReferenceException को फेंकने की संभावना को दूर करने के लिए उदाहरण को अपडेट किया। IsCheckedएक अशक्त प्रकार है इसलिए वापस लौटना Nullable<Boolean>एक उचित समाधान लगता है।


26
मैं सहमत हूं, मेरा मानना ​​है कि यह एक बेहतर समाधान है। इसके अलावा, इस रूपांतरण का उपयोग करने से परियोजना को संकलन समय पर टूट जाएगा, समय नहीं चलेगा, अगर गणना मूल्यों को बदल दिया जाता है, जो एक बड़ा लाभ है।
क्रिमसनएक्स

4
यह निश्चित रूप से स्वीकृत एक से बेहतर समाधान है। +1
OrPaz

7
अच्छा समाधान। मुझे लगता है कि यह वास्तव में सिर्फ 2 मूल्यों की तुलना एक तुलना कनवर्टर है जोड़ देगा। यह EnumToBooleanConverter की तुलना में एक अधिक सामान्य नाम हो सकता है जैसे कि
CompisonConverter

5
@ स्कॉट, बहुत अच्छा। यह कनवर्टर किसी भी मामले में, झंडे विशेषता के साथ या इसके बिना अच्छा है। लेकिन यह ज्यादातर इस मामले में मूर्खतापूर्ण होगा कि इस फिल्टर को सीधे ध्वज के रूप में एनम के साथ प्रयोग करें। कारण यह है कि आपको उचित परिणाम प्राप्त करने के लिए पिछले मूल्य के साथ बूलियन कैल्क (! = = या ^ =) प्राप्त करना चाहिए, लेकिन कनवर्टर में पिछले मूल्य तक पहुंच नहीं है। फिर आपको प्रत्येक एनुम मूल्य के लिए एक बूल जोड़ना चाहिए और उचित बूलियन को अपने MVVM मॉडल में स्वयं करना चाहिए। लेकिन हर जानकारी के लिए धन्यवाद, बहुत उपयोगी।
एरिक ओउलेट 20

2
विंडोज फोन 8 में (संभवतः विन स्टोर ऐप्स के मामले में) हमारे पास x: स्टेटिक नहीं है, इसलिए हम सीधे यहां समाधान का उपयोग नहीं कर सकते हैं। हालाँकि IDE / Complier काफी स्मार्ट है, और सभी स्ट्रिंग शाब्दिकों के खिलाफ स्ट्रिंग को देखता है (वैसे भी मेरा अनुमान है)। जैसे यह काम करता है <RadioButton IsChecked = "{बाइंडिंग ट्रैकिंगमोड, कन्वर्टरपर्मेट = ड्राइविंग, कनवर्टर = {StaticResource EnumToBooleanConverter}, Mode = TwoWay}" / ड्राइविंग में कोई भी टाइपो रन समय के बजाय डिजाइन / संकलन समय के दौरान पकड़ा जाएगा।
आदर्श

26

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

http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.convertback.aspx http://msdn.microsoft.com/en-us/library/system.windows.data.binding .donothing.aspx


कोई बंधन नहीं है। चांदी की रोशनी में सुखदायक। यह केवल WPF है। इसके बजाय अशक्त का उपयोग करें।
अलेक्जेंडर वासिलीव

1
बाइंडिंग। नीडिंग भी UWP से चला गया है।
BlackICE

5

मैं एक ListBox में RadioButtons का उपयोग करेगा, और उसके बाद SelectValue को बाँध देगा।

यह इस विषय के बारे में एक पुराना सूत्र है, लेकिन आधार विचार समान होना चाहिए: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/323d067a-efef-4cnf-8d99-fecf45522395/


मुझे लिस्टबॉक्स और डेटाटेम्पलेट का उपयोग करके एक समान तरीके से दो-तरफा बाइंडिंग मिलती है, इसलिए आपको चाहिए।
ब्रायन एंडरसन

यह बग: geekswithblogs.net/claraoscura/archive/2008/10/17/125901.aspx ने मेरे लिए एक दिन बर्बाद कर दिया।
गला दबाना

3
यह अब तक का सबसे अच्छा समाधान है, बाकी सब कुछ निरर्थक कोड का कारण बनता है। ( लिस्टबॉक्स का उपयोग करने का एक और उदाहरण )
एचबी

3

UWP के लिए, यह इतना सरल नहीं है: एक पैरामीटर के रूप में फ़ील्ड मान को पारित करने के लिए आपको अतिरिक्त घेरा से कूदना होगा।

उदाहरण 1

WPF और UWP दोनों के लिए मान्य।

<MyControl>
    <MyControl.MyProperty>
        <Binding Converter="{StaticResource EnumToBooleanConverter}" Path="AnotherProperty">
            <Binding.ConverterParameter>
                <MyLibrary:MyEnum>Field</MyLibrary:MyEnum>
            </Binding.ConverterParameter>
        </MyControl>
    </MyControl.MyProperty>
</MyControl>

उदाहरण 2

WPF और UWP दोनों के लिए मान्य।

...
<MyLibrary:MyEnum x:Key="MyEnumField">Field</MyLibrary:MyEnum>
...

<MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={StaticResource MyEnumField}}"/>

उदाहरण 3

केवल WPF के लिए मान्य!

<MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static MyLibrary:MyEnum.Field}}"/>

UWP समर्थन नहीं करता है x:Staticइसलिए उदाहरण 3 प्रश्न से बाहर है; मानकर आप उदाहरण 1 के साथ चलते हैं , परिणाम अधिक क्रिया कोड है। उदाहरण 2 थोड़ा बेहतर है, लेकिन फिर भी आदर्श नहीं है।

समाधान

public abstract class EnumToBooleanConverter<TEnum> : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var Parameter = parameter as string;

        if (Parameter == null)
            return DependencyProperty.UnsetValue;

        if (Enum.IsDefined(typeof(TEnum), value) == false)
            return DependencyProperty.UnsetValue;

        return Enum.Parse(typeof(TEnum), Parameter).Equals(value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        var Parameter = parameter as string;
        return Parameter == null ? DependencyProperty.UnsetValue : Enum.Parse(typeof(TEnum), Parameter);
    }
}

फिर, प्रत्येक प्रकार के लिए आप समर्थन करना चाहते हैं, एक कनवर्टर को परिभाषित करें जो एनम प्रकार को बॉक्स करता है।

public class MyEnumToBooleanConverter : EnumToBooleanConverter<MyEnum>
{
    //Nothing to do!
}

इसका कारण बॉक्सिंग होना चाहिए क्योंकि ConvertBackविधि के प्रकार को संदर्भित करने का कोई तरीका प्रतीत नहीं होता है ; मुक्केबाजी उस का ख्याल रखती है। यदि आप पहले दो उदाहरणों में से किसी एक के साथ जाते हैं, तो आप बस पैरामीटर प्रकार को संदर्भित कर सकते हैं, एक बॉक्सिंग वर्ग से विरासत की आवश्यकता को समाप्त कर सकते हैं; यदि आप यह सब एक पंक्ति में करना चाहते हैं और कम से कम वाचालता संभव है, तो बाद वाला समाधान आदर्श है।

उपयोग उदाहरण 2 से मिलता जुलता है , लेकिन वास्तव में, कम क्रिया है।

<MyControl MyProperty="{Binding AnotherProperty, Converter={StaticResource MyEnumToBooleanConverter}, ConverterParameter=Field}"/>

नकारात्मक पक्ष यह है कि आपको प्रत्येक प्रकार के लिए एक कनवर्टर को परिभाषित करना चाहिए जिसे आप समर्थन करना चाहते हैं।


1

मैंने एक नया वर्ग बनाया है ताकि बंधे हुए रेडियोबटन और चेकबॉक्‍स को एनमोंस से जोड़ा जा सके। यह फ्लैग किए गए एनम के लिए (कई चेकबॉक्स चयन के साथ) और एकल-चयन चेकबॉक्स या रेडियो बटन के लिए गैर-फ्लैग किए गए एनम के लिए काम करता है। इसके लिए किसी भी तरह के मूल्यवर्धक की आवश्यकता नहीं है।

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

public class EnumSelection<T> : INotifyPropertyChanged where T : struct, IComparable, IFormattable, IConvertible
{
  private T value; // stored value of the Enum
  private bool isFlagged; // Enum uses flags?
  private bool canDeselect; // Can be deselected? (Radio buttons cannot deselect, checkboxes can)
  private T blankValue; // what is considered the "blank" value if it can be deselected?

  public EnumSelection(T value) : this(value, false, default(T)) { }
  public EnumSelection(T value, bool canDeselect) : this(value, canDeselect, default(T)) { }
  public EnumSelection(T value, T blankValue) : this(value, true, blankValue) { }
  public EnumSelection(T value, bool canDeselect, T blankValue)
  {
    if (!typeof(T).IsEnum) throw new ArgumentException($"{nameof(T)} must be an enum type"); // I really wish there was a way to constrain generic types to enums...
    isFlagged = typeof(T).IsDefined(typeof(FlagsAttribute), false);

    this.value = value;
    this.canDeselect = canDeselect;
    this.blankValue = blankValue;
  }

  public T Value
  {
    get { return value; }
    set 
    {
      if (this.value.Equals(value)) return;
      this.value = value;
      OnPropertyChanged();
      OnPropertyChanged("Item[]"); // Notify that the indexer property has changed
    }
  }

  [IndexerName("Item")]
  public bool this[T key]
  {
    get
    {
      int iKey = (int)(object)key;
      return isFlagged ? ((int)(object)value & iKey) == iKey : value.Equals(key);
    }
    set
    {
      if (isFlagged)
      {
        int iValue = (int)(object)this.value;
        int iKey = (int)(object)key;

        if (((iValue & iKey) == iKey) == value) return;

        if (value)
          Value = (T)(object)(iValue | iKey);
        else
          Value = (T)(object)(iValue & ~iKey);
      }
      else
      {
        if (this.value.Equals(key) == value) return;
        if (!value && !canDeselect) return;

        Value = value ? key : blankValue;
      }
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private void OnPropertyChanged([CallerMemberName] string propertyName = "")
  {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

और इसका उपयोग कैसे करें, मान लें कि आपके पास मैन्युअल या स्वचालित रूप से कार्य चलाने के लिए एक एनुम है, और इसे सप्ताह के किसी भी दिन के लिए निर्धारित किया जा सकता है, और कुछ वैकल्पिक विकल्प ...

public enum StartTask
{
  Manual,
  Automatic
}

[Flags()]
public enum DayOfWeek
{
  Sunday = 1 << 0,
  Monday = 1 << 1,
  Tuesday = 1 << 2,
  Wednesday = 1 << 3,
  Thursday = 1 << 4,
  Friday = 1 << 5,
  Saturday = 1 << 6
}

public enum AdditionalOptions
{
  None = 0,
  OptionA,
  OptionB
}

अब, इस वर्ग का उपयोग करना कितना आसान है:

public class MyViewModel : ViewModelBase
{
  public MyViewModel()
  {
    StartUp = new EnumSelection<StartTask>(StartTask.Manual);
    Days = new EnumSelection<DayOfWeek>(default(DayOfWeek));
    Options = new EnumSelection<AdditionalOptions>(AdditionalOptions.None, true, AdditionalOptions.None);
  }

  public EnumSelection<StartTask> StartUp { get; private set; }
  public EnumSelection<DayOfWeek> Days { get; private set; }
  public EnumSelection<AdditionalOptions> Options { get; private set; }
}

और यहाँ चेकबॉक्स और रेडियो बटन को इस वर्ग के साथ बाँधना कितना आसान है:

<StackPanel Orientation="Vertical">
  <StackPanel Orientation="Horizontal">
    <!-- Using RadioButtons for exactly 1 selection behavior -->
    <RadioButton IsChecked="{Binding StartUp[Manual]}">Manual</RadioButton>
    <RadioButton IsChecked="{Binding StartUp[Automatic]}">Automatic</RadioButton>
  </StackPanel>
  <StackPanel Orientation="Horizontal">
    <!-- Using CheckBoxes for 0 or Many selection behavior -->
    <CheckBox IsChecked="{Binding Days[Sunday]}">Sunday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Monday]}">Monday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Tuesday]}">Tuesday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Wednesday]}">Wednesday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Thursday]}">Thursday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Friday]}">Friday</CheckBox>
    <CheckBox IsChecked="{Binding Days[Saturday]}">Saturday</CheckBox>
  </StackPanel>
  <StackPanel Orientation="Horizontal">
    <!-- Using CheckBoxes for 0 or 1 selection behavior -->
    <CheckBox IsChecked="{Binding Options[OptionA]}">Option A</CheckBox>
    <CheckBox IsChecked="{Binding Options[OptionB]}">Option B</CheckBox>
  </StackPanel>
</StackPanel>
  1. जब UI लोड होता है, तो "मैनुअल" रेडियो बटन का चयन किया जाएगा और आप "मैनुअल" या "स्वचालित" के बीच अपने चयन को बदल सकते हैं लेकिन उनमें से किसी एक को हमेशा चुना जाना चाहिए।
  2. सप्ताह के हर दिन अनियंत्रित होंगे, लेकिन उनमें से किसी भी संख्या को चेक या अनचेक किया जा सकता है।
  3. "विकल्प ए" और "विकल्प बी" दोनों शुरू में अनियंत्रित होंगे। आप एक या दूसरे को चेक कर सकते हैं, एक की जांच दूसरे को अनचेक करेंगे (रेडियोबटन की तरह), लेकिन अब आप उन दोनों को भी अनचेक कर सकते हैं (जो आप WPF के रेडियोबटन के साथ नहीं कर सकते हैं, यही कारण है कि यहां चेकबॉक्स का उपयोग किया जा रहा है)

मान लीजिए कि आपके पास StartTask enum में 3 आइटम हैं जैसे {Undefined, Manual, Automatic} आप डिफ़ॉल्ट रूप से डिफ़ॉल्ट होना चाहते हैं क्योंकि जब तक कोई उपयोगकर्ता मान निर्धारित नहीं करता है, तब तक यह अपरिभाषित है। यह भी: सेलेक्ट इटम कैसे निपटा जाता है? आपके ViewModel का कोई SelectStartTask नहीं है।
user1040323

मेरे ViewModel में, StartUp संपत्ति एक EnumSelection<StartTask>वस्तु है। यदि आप परिभाषा को EnumSelection<T>देखते हैं , तो आप देख सकते हैं कि इसके पास एक मूल्य संपत्ति है। तो देखने के मॉडल के लिए एक "SelectStartTask" की आवश्यकता नहीं है। आप उपयोग करेंगे StartUp.Value। और अपरिभाषित का एक डिफ़ॉल्ट मान होने के लिए, 3 एनुम, अतिरिक्त विवरण देखें, इसमें एक अपरिभाषित के बजाय कोई नहीं है, लेकिन आप इसका नाम बदल सकते हैं जो आप चाहते हैं।
निक

1

चेकबॉक्स के लिए भी यह काम करता है।

public class EnumToBoolConverter:IValueConverter
{
    private int val;
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int intParam = (int)parameter;
        val = (int)value;

        return ((intParam & val) != 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        val ^= (int)parameter;
        return Enum.Parse(targetType, val.ToString());
    }
}

एक एकल को कई चेकबॉक्स में बाँधना।


1
आपके लिए मेरे द्वारा किए गए उपकार के लिए मैं आपसे एक बड़ा "THANKS" कहता हूं। यह मेरे लिए एक आकर्षण की तरह काम किया है।
एल्हम आज़ादफ़र

0

स्कॉट से EnumToBooleanConverter के आधार पर। मैंने देखा कि ConvertBack विधि Enum पर ध्वज कोड के साथ काम नहीं करती है।

मैंने निम्नलिखित कोड आज़माया है:

public class EnumHasFlagToBooleanConverter : IValueConverter
    {
        private object _obj;
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            _obj = value;
            return ((Enum)value).HasFlag((Enum)parameter);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value.Equals(true))
            {
                if (((Enum)_obj).HasFlag((Enum)parameter))
                {
                    // Do nothing
                    return Binding.DoNothing;
                }
                else
                {
                    int i = (int)_obj;
                    int ii = (int)parameter;
                    int newInt = i+ii;
                    return (NavigationProjectDates)newInt;
                }
            }
            else
            {
                if (((Enum)_obj).HasFlag((Enum)parameter))
                {
                    int i = (int)_obj;
                    int ii = (int)parameter;
                    int newInt = i-ii;
                    return (NavigationProjectDates)newInt;

                }
                else
                {
                    // do nothing
                    return Binding.DoNothing;
                }
            }
        }
    }

केवल एक चीज जो मुझे काम करने के लिए नहीं मिल सकती है, वह है एक कास्ट से ऐसा intकरने के लिए, targetTypeइसलिए मैंने इसे हार्डकोड किया NavigationProjectDates, जो मैं उपयोग करता हूं। और, targetType == NavigationProjectDates...


अधिक सामान्य झंडे Enum कनवर्टर के लिए संपादित करें:

    सार्वजनिक वर्ग FlagsEnumToBooleanConverter: IValueConverter {
        निजी int _flags = 0;
        सार्वजनिक ऑब्जेक्ट कन्वर्ट (ऑब्जेक्ट वैल्यू, टाइप टारगेट टाइप, ऑब्जेक्ट पैरामीटर, स्ट्रिंग भाषा) {
            अगर (मान == अशक्त) गलत है;
            _flags = (int) मूल्य;
            टाइप t = value.GetType ();
            ऑब्जेक्ट o = Enum.ToObject (टी, पैरामीटर);
            वापसी (Enum) मान) .HasFlag ((Enum) o);
        }

        सार्वजनिक ऑब्जेक्ट ConvertBack (ऑब्जेक्ट मान, प्रकार targetType, ऑब्जेक्ट पैरामीटर, स्ट्रिंग भाषा)
        {
            अगर (मान?
                _flags = _flags | (int) पैरामीटर;
            }
            अन्य {
                _flags = _flags & ~ (int) पैरामीटर;
            }
            वापसी _flags;
        }
    }

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

0

आप रेडियो बटन को गतिशील रूप से बना ListBoxसकते हैं, आपको कन्वर्टर्स के बिना, काफी सरल बनाने में मदद कर सकते हैं।

संक्षिप्त चरण नीचे दिए गए हैं: एक सूची बॉक्स बनाएं और सूची के लिए आइटम स्रोत को एनम के रूप में सेट करें और सूची MyLovelyEnumमें चयनित बॉक्स को VeryLovelyEnumसंपत्ति में बांध दें । फिर प्रत्येक ListBoxItem के लिए रेडियो बटन बनाए जाएंगे।

  • चरण 1 : अपने विंडो, यूजरकंट्रोल या ग्रिड आदि के लिए स्थिर संसाधनों में एनम जोड़ें।
    <Window.Resources>
        <ObjectDataProvider MethodName="GetValues"
                            ObjectType="{x:Type system:Enum}"
                            x:Key="MyLovelyEnum">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:MyLovelyEnum" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
  • चरण 2 : सूची बॉक्स का उपयोग करें औरControl Template प्रत्येक आइटम को रेडियो बटन के रूप में पॉप्युलेट करें
    <ListBox ItemsSource="{Binding Source={StaticResource MyLovelyEnum}}" SelectedItem="{Binding VeryLovelyEnum, Mode=TwoWay}" >
        <ListBox.Resources>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <RadioButton
                                Content="{TemplateBinding ContentPresenter.Content}"
                                IsChecked="{Binding Path=IsSelected,
                                RelativeSource={RelativeSource TemplatedParent},
                                Mode=TwoWay}" />
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.Resources>
    </ListBox>

लाभ के नीचे है: अगर किसी दिन अपने enum वर्ग में परिवर्तन, आप जीयूआई (XAML फाइल) को अद्यतन करने की जरूरत नहीं है।

संदर्भ: https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.