Osama Javed
Osama Javed

Reputation: 1442

How to change context menu item's style if command is disabled

I have a context menu and at certain point i disable some of the commands bound to context menu items.

what works:

when the command gets disabled , clicking on the menu item does not call the execute method on the command as i wanted.

What does not work:

Both commands that can exucute and those which cant look identical!! my users cant tell the difference.

Problem:

How can I change the style to display this change. Change in background color, border color, foreground color , a tooltip... anything will be acceptable..

I experimented with xaml and was unable to solve this. (I am a noob with xaml so my attempts are not even worth pasting here :) )

xaml :

<Border BorderThickness="1" MinWidth="100"  Background="Transparent"  ContextMenu="{Binding Path=ContextMenu}" BorderBrush="{Binding Path=BorderColor}">

Binding:

public override ContextMenu ContextMenu
        {
            get
            {
                return new ContextMenu
                           {
                               ItemsSource = new ObservableCollection<MenuItem>
                                                 {
                                                     new MenuItem
                                                         {
                                                             Header = IsSharedFieldView? "Delete Shared Field" :"Delete Field" ,
                                                             Command = DeleteFieldCommand 
                                                         }
                                                 }
                           };

            }
        }

Upvotes: 1

Views: 2522

Answers (3)

Osama Javed
Osama Javed

Reputation: 1442

Solution that worked :

Initially i was binding a ContextMenu from my view model and the isEnabled was not working.

Instead of that I created the context menu in xaml and bound the itemsSource from the viewModel.

Now the menu item gets disabled and the triggers are working.

Not sure what i was doing wrong but this fixed it :)

Upvotes: 0

Louis Kottmann
Louis Kottmann

Reputation: 16618

The trick here, is that ContextMenu actually inherits from ItemsControl, this works on my machine:

/// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            this.DataContext = this;
            InitializeComponent();

            MenuItems = new ObservableCollection<KeyValuePair<string, ICommand>>();
            MenuItems.Add(new KeyValuePair<string, ICommand>("One", OneCommand));
            MenuItems.Add(new KeyValuePair<string, ICommand>("Two", null));
        }

        public ObservableCollection<KeyValuePair<String, ICommand>> MenuItems { get; set; }

        #region OneCommand
        DelegateCommand _OneCommand;
        public DelegateCommand OneCommand
        {
            get { return _OneCommand ?? (_OneCommand = new DelegateCommand(One, CanOne)); }
        }

        public bool CanOne()
        {
            return false;
        }

        public void One()
        {

        }
        #endregion
    }

And the XAML:

<Window x:Class="DynamicContextMenuTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Path Data="M 10,2 L 17.5,2 L 17.5,0 L 23,4.5 L 17.5,9 L 17.5,7.3 L 10,7.3 L 10,2" Fill="Green">
            <Path.ContextMenu>
                <ContextMenu ItemsSource="{Binding MenuItems}" DisplayMemberPath="Key">
                    <ContextMenu.Resources>
                        <Style TargetType="MenuItem">
                            <Setter Property="Command" Value="{Binding Value}" />
                            <Style.Triggers>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Background" Value="Red" />
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </ContextMenu.Resources>
                </ContextMenu>
            </Path.ContextMenu>
        </Path>
    </Grid>
</Window>

Notice a few things:

  • You no longer bind to a ContextMenu (viewmodels shouldn't be aware of controls), instead you bind to a collection of string(Header)/ICommand(Command)
  • When an item's command's CanExecute returns false, the bound control's IsEnabled property becomes false. You can have a trigger on that property to modify the appearance of the bound control.

Upvotes: 3

yo chauhan
yo chauhan

Reputation: 12295

    <Window.Resources>
        <Style TargetType="{x:Type MenuItem}">
            <Style.Triggers>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="Background" Value="Black"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <TextBox >
            <TextBox.ContextMenu>
                <ContextMenu>
                    <Menu>
                        <MenuItem Header="Add" IsEnabled="False"/>
                        <MenuItem Header="Delete"/>
                    </Menu>
                </ContextMenu>
            </TextBox.ContextMenu>
        </TextBox>
    </Grid>

Its just demo and you can have idea from this . and you can bind IsEnabled to your VM Command.CanExecute . I hope this will help.

Upvotes: 1

Related Questions