[wpf] Come legare i RadioButton a un enum?


Answers

È possibile semplificare ulteriormente la risposta accettata. Invece di digitare enum come stringhe in xaml e fare più lavoro nel tuo convertitore del necessario, puoi passare esplicitamente il valore enum invece di una rappresentazione stringa e, come commentato CrimsonX, gli errori vengono lanciati in fase di compilazione piuttosto che in runtime:

ConverterParameter = {x: Statico locale: YourEnumType.Enum1}

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

Quindi semplificare il convertitore:

public class EnumToBooleanConverter : 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) ? parameter : Binding.DoNothing;
    }
}

Nota: gruppi multipli di RadioButton nello stesso container (17 febbraio 11):

In xaml, se i pulsanti di opzione condividono lo stesso contenitore padre, quindi selezionarne uno deselezionerà tutti gli altri all'interno di quel contenitore (anche se sono associati a una proprietà diversa). Quindi cerca di mantenere i tuoi RadioButton associati a una proprietà comune raggruppati insieme nel proprio contenitore come un pannello di stack. Nei casi in cui i RadioButton correlati non possono condividere un singolo contenitore padre, impostare la proprietà GroupName di ciascun RadioButton su un valore comune per raggrupparli logicamente.

Nota - Tipo Enum nidificato in una classe (28 aprile 11):

Se il tuo tipo di enum è annidato in una classe (piuttosto che direttamente nello spazio dei nomi), potresti essere in grado di utilizzare la sintassi '+' per accedere all'enumerazione in XAML come indicato in una risposta (non contrassegnata) alla domanda Impossibile trovare tipo enum per riferimento statico in WPF :

ConverterParameter = {x: Statico locale: YourClass + YourNestedEnumType.Enum1}

A causa di questo problema Microsoft Connect , tuttavia, il designer in VS2010 non caricherà più "Type 'local:YourClass+YourNestedEnumType' was not found." , ma il progetto viene compilato ed eseguito correttamente. Naturalmente, è possibile evitare questo problema se si è in grado di spostare direttamente il tipo di enum nello spazio dei nomi.

Modifica (16 dicembre 10):

Grazie ad anon per aver suggerito di restituire Binding.DoNothing piuttosto che DependencyProperty.UnsetValue.

Modifica (5 aprile 11):

Semplificato ConvertBack's if-else per utilizzare un operatore ternario.

Modifica (27 gennaio 12):

Se si utilizzano i flag Enum, il convertitore sarà il seguente:

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;
    }
}

Modifica (7 maggio 15):

Nel caso di un Enum Nullable (che non viene richiesto nella domanda, ma può essere necessario in alcuni casi, ad esempio, ORM restituisce null dal DB o ogni qualvolta potrebbe avere senso che nella logica del programma il valore non sia fornito), ricordarsi di aggiungere un controllo Null iniziale nel Metodo di conversione e restituisce il valore bool appropriato, che in genere è falso (se non si desidera selezionare alcun pulsante di opzione), come di seguito:

    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);
    }
Question

Ho un enume come questo:

public enum MyLovelyEnum
{
  FirstSelection,
  TheOtherSelection,
  YetAnotherOne
};

Ho ottenuto una proprietà nel mio DataContext:

public MyLovelyEnum VeryLovelyEnum { get; set; }

E ho ottenuto tre RadioButton nel mio client WPF.

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

Ora, come posso legare i RadioButton alla proprietà per un corretto collegamento a due vie?




Basato sull'EnumToBooleanConverter di Scott. Ho notato che il metodo ConvertBack non funziona su Enum con codice flag.

Ho provato il seguente codice:

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;
                }
            }
        }
    }

L'unica cosa che non riesco a far funzionare è di fare un cast da int a targetType quindi l'ho reso codificato in NavigationProjectDates , l'enum che uso. E, targetType == NavigationProjectDates ...

Modifica per più generico convertitore Flags Enum:

    public class FlagsEnumToBooleanConverter : IValueConverter {
        private int _flags=0;
        public object Convert(object value, Type targetType, object parameter, string language) {
            if (value == null) return false;
            _flags = (int) value;
            Type t = value.GetType();
            object o = Enum.ToObject(t, parameter);
            return ((Enum)value).HasFlag((Enum)o);
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            if (value?.Equals(true) ?? false) {
                _flags = _flags | (int) parameter;
            }
            else {
                _flags = _flags & ~(int) parameter;
            }
            return _flags;
        }
    }









Related