[wpf] Cómo vincular RadioButtons a una enumeración?


3 Answers

Puedes simplificar aún más la respuesta aceptada. En lugar de escribir las enumeraciones como cadenas en xaml y hacer más trabajo de lo necesario, puede pasar explícitamente el valor enum en lugar de una representación de cadena, y como comentó CrimsonX, los errores se lanzan en tiempo de compilación en lugar de tiempo de ejecución:

ConverterParameter = {x: Static local: 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>

Luego simplifica el convertidor:

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: varios grupos de RadioButtons en el mismo contenedor (17 de febrero de 2011):

En xaml, si los botones de radio comparten el mismo contenedor principal, al seleccionar uno se anulará la selección de todos los demás dentro de ese contenedor (incluso si están vinculados a una propiedad diferente). Intente mantener sus RadioButton's unidos a una propiedad común agrupados en su propio contenedor como un panel de pila. En los casos donde sus RadioButtons relacionados no pueden compartir un solo contenedor principal, establezca la propiedad GroupName de cada RadioButton en un valor común para agruparlos de manera lógica.

Nota: tipo de Enum anidado en una clase (28 de abril de 2011):

Si su tipo de enumeración está anidado en una clase (en lugar de directamente en el espacio de nombres), es posible que pueda utilizar la sintaxis '+' para acceder a la enumeración en XAML como se indica en una respuesta (no marcada) a la pregunta No se puede encontrar tipo enum para referencia estática en WPF :

ConverterParameter = {x: Estático local: YourClass + YourNestedEnumType.Enum1}

Sin embargo, debido a este problema de conexión de Microsoft , el diseñador en VS2010 ya no cargará al indicar "Type 'local:YourClass+YourNestedEnumType' was not found." , pero el proyecto se compila y ejecuta con éxito. Por supuesto, puede evitar este problema si puede mover su tipo de enumeración directamente al espacio de nombres.

Editar (16 de diciembre '10):

Gracias a anon por sugerir devolver Binding.DoNothing en lugar de DependencyProperty.UnsetValue.

Editar (5 de abril de 2011):

Simplified ConvertBack's if-else para usar un Operador Ternario.

Editar (27 de enero de 12):

Si usa banderas Enum, el convertidor sería el siguiente:

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

Editar (7 de mayo de 15):

En el caso de un Enum Nullable (que no se pregunta en la pregunta, pero puede ser necesario en algunos casos, por ejemplo, ORM devuelve nulo de DB o siempre que tenga sentido que en la lógica del programa no se proporcione el valor), recuerde agregar una comprobación inicial nula en el Método de conversión y devuelve el valor de bool apropiado, que normalmente es falso (si no desea que se seleccione ningún botón de opción), como a continuación:

    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

Tengo una enumeración como esta:

public enum MyLovelyEnum
{
  FirstSelection,
  TheOtherSelection,
  YetAnotherOne
};

Obtuve una propiedad en mi DataContext:

public MyLovelyEnum VeryLovelyEnum { get; set; }

Y obtuve tres RadioButtons en mi cliente WPF.

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

Ahora, ¿cómo puedo vincular los RadioButtons a la propiedad para un enlace bidireccional correcto?




Basado en el EnumToBooleanConverter de Scott. Noté que el método ConvertBack no funciona en el Enum con el código flags.

Probé el siguiente código:

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

Lo único que no puedo hacer es targetType un elenco de int a targetType así que lo targetType en NavigationProjectDates , la enumeración que uso. Y, targetType == NavigationProjectDates ...

Edite para un convertidor más genérico 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