Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - how to hide menu item if command's CanExecute is false?

By default menu items become disabled when its command cannot be executed (CanExecute = false). What is the easiest way to make the menu item visible/collapsed based on the CanExecute method?

like image 635
Gus Cavalcanti Avatar asked Sep 21 '10 15:09

Gus Cavalcanti


3 Answers

Thanks for the solution. For those wanting explicit XAML this might help:

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

In my case, the context menu is a resource, so the binding for the visibility must use the RelativeSource Self binding setup.

As a side, for the CommandParameter, you might also pass the DataContext of the item whom was clicked to open the context menu. And in order to route the command bindings to the parent window, you will need to set the CommandTarget accordingly also.

like image 93
Reddog Avatar answered Sep 21 '22 18:09

Reddog


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

CanExecute toggles the IsEnabled property so just watch this and keep everything in the UI. Create a separate style if you want to reuse this.

like image 28
rjarmstrong Avatar answered Sep 18 '22 18:09

rjarmstrong


You can simply bind Visibility to IsEnabled (set to false on CanExecute == false). You still would need an IValueConverter to convert the bool to visible/collapsed.

    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
    }
like image 44
MrDosu Avatar answered Sep 20 '22 18:09

MrDosu