Por defecto de los elementos de menú se deshabilitan cuando su comando no puede ser ejecutado (CanExecute = false). ¿Cuál es la manera más fácil de hacer que el elemento de menú ver/derrumbó basado en el método CanExecute?

6 Comentarios

  1. 43

    Usted puede simplemente enlazar Visibilidad a IsEnabled (establecida en false en CanExecute == false).
    Usted todavía necesita un IValueConverter para convertir el bool visible/derrumbó.

        public class BooleanToCollapsedVisibilityConverter : IValueConverter
        {
            #region IValueConverter Members
    
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                //reverse conversion (false=>Visible, true=>collapsed) on any given parameter
                bool input = (null == parameter) ? (bool)value : !((bool)value);
                return (input) ? Visibility.Visible : Visibility.Collapsed;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
    
            #endregion
        }
    • Este es un esfuerzo un poco más de lo necesario, puede usar un trigger
  2. 52

    Gracias por la solución. Para aquellos que quieran explícita XAML esto podría ayudar a:

    <Window.Resources>
            <BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" />
    </Window.Resources>
    
    <ContextMenu x:Key="innerResultsContextMenu">
        <MenuItem Header="Open"
                  Command="{x:Static local:Commands.AccountOpened}"
                  CommandParameter="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" 
                  CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"
                  Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Mode=OneWay, Converter={StaticResource booleanToVisibilityConverter}}" 
                  />
    </ContextMenu>

    En mi caso, el menú de contexto es un recurso, por lo que el enlace para la visibilidad debe utilizar el RelativeSource Auto de unión de la instalación.

    Un lado, para el CommandParameter, también podría pasar el DataContext del elemento los cuales se hace clic para abrir el menú contextual. Y en el fin de la ruta el comando enlaces a la ventana principal, usted tendrá que establecer el CommandTarget en consecuencia también.

  3. 45
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Visibility" Value="Collapsed"/>
        </Trigger>
    </Style.Triggers>

    CanExecute alterna el IsEnabled propiedad por lo que acaba de ver esto y mantener todo en la interfaz de usuario. Crear un estilo independiente si desea volver a utilizar este.

    • Esto es perfecto – trabajó como un encanto (aunque he utilizado un enlace directo con un bool a la visibilidad del convertidor en lugar de un desencadenador, la idea es la misma)
    • La visibilidad debe ser ajustado a Collapsed ya que de lo contrario el menú oculto elemento se siguen ocupando espacio.
    • Sí, esta es una solución mejor, aunque como Romano por la sugerencia, la visibilidad se debe establecer a colapsar
    • Cambiar la visibilidad a ‘Colapsado’.
    • cambiar la visibilidad es un cambio de estilo para el uso de un estilo tiene más sentido que la de un enlace directo
  4. 1

    No sé si esta es la manera más fácil, pero siempre se puede crear una propiedad que devuelve el CanExecute() y, a continuación, enlazar la Visibilidad de su elemento a esta propiedad, el uso de un IValueConverter para convertir el valor booleano para la Visibilidad.

    • Esta respuesta no ayuda mucho, pero se la voy a dar +1 a nivel de los puntos negativos de que estoy completamente de no entendía por qué alguien le ha dado. Mientras que esta respuesta no es demasiado útil, TODAS las cosas mencionadas son VÁLIDAS y por otra parte, todos los demás de manera positiva marcada respuestas de HACER USO de las cosas mencionadas. Al menos pointvalue esta respuesta se merece es cero, no los negativos!
    • Esta era mi idea inicial, pero ¿cómo se puede obtener acceso al objeto (param) parámetro dentro de esta nueva propiedad, y se pasa a CanExecute()?
  5. 0

    Unión Visibilidad a IsEnabled hace el truco, pero la necesaria XAML es desagradablemente largo y complicado:

    Visibility="{Binding Path=IsEnabled, RelativeSource={RelativeSource Self}, Mode=OneWay, Converter={StaticResource booleanToVisibilityConverter}}"

    Puede utilizar una propiedad asociada a ocultar todos los detalles de unión y transmitir claramente su intención.

    Aquí es la propiedad adjunta:

    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    
    namespace MyNamespace
    {
        public static class Bindings
        {
            public static bool GetVisibilityToEnabled(DependencyObject obj)
            {
                return (bool)obj.GetValue(VisibilityToEnabledProperty);
            }
    
            public static void SetVisibilityToEnabled(DependencyObject obj, bool value)
            {
                obj.SetValue(VisibilityToEnabledProperty, value);
            }
            public static readonly DependencyProperty VisibilityToEnabledProperty =
                DependencyProperty.RegisterAttached("VisibilityToEnabled", typeof(bool), typeof(Bindings), new PropertyMetadata(false, OnVisibilityToEnabledChanged));
    
            private static void OnVisibilityToEnabledChanged(object sender, DependencyPropertyChangedEventArgs args)
            {
                if (sender is FrameworkElement element)
                {
                    if ((bool)args.NewValue)
                    {
                        Binding b = new Binding
                        {
                            Source = element,
                            Path = new PropertyPath(nameof(FrameworkElement.IsEnabled)),
                            Converter = new BooleanToVisibilityConverter()
                        };
                        element.SetBinding(UIElement.VisibilityProperty, b);
                    }
                    else
                    {
                        BindingOperations.ClearBinding(element, UIElement.VisibilityProperty);
                    }
                }
            }
        }
    }

    Y aquí es cómo utilizar:

    <Window x:Class="MyNamespace.SomeClass"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:MyNamespace">
    
        <ContextMenu x:Key="bazContextMenu">
            <MenuItem Header="Open"
                      Command="{x:Static local:FooCommand}"
                      local:Bindings.VisibilityToEnabled="True"/>
        </ContextMenu>
    </Window>

Dejar respuesta

Please enter your comment!
Please enter your name here