Mattias K


Hi!

How should I implement my context menu items in order to enable/disable (or show/collapse) them depeding on the item selected

Best regards,

Mattias



Re: Adaptive context menus

Yi-Lun Luo - MSFT


Hello, you can use data binding. Here¡¯s a sample:

Suppose you want to build a ContextMenu for your items in a ListBox. The data source is:

public class TestData

{

private string name;

public string Name

{

get { return name; }

set { name = value; }

}

private bool enabled;

public bool Enabled

{

get { return enabled; }

set { enabled = value; }

}

}

Let¡¯s set the Window¡¯s DataContext to a collection of TestData in its constructor. (I¡¯m using C# 3.5 to simplify the initialize task.)

this.DataContext = new TestData[] { new TestData { Name = "a", Enabled = true }, new TestData { Name = "b", Enabled = false } };

Since DataContext was set in the constructor, in the Window¡¯s Loaded event, the ListBox¡¯s items should have been generated. So we can use:

private void Window_Loaded(object sender, RoutedEventArgs e)

{

ContextMenu menu = (ContextMenu)this.Resources["cm"];

foreach (object obj in listBox1.Items)

{

ListBoxItem item = (ListBoxItem)listBox1.ItemContainerGenerator.ContainerFromItem(obj);

item.ContextMenu = menu;

}

}

This ContextMenu is defined in resources. We bind its IsEnabled property to the Enabled property in data source:

<ContextMenu x:Key="cm">

<MenuItem Header="Test" IsEnabled="{Binding Path=Enabled}"/>

</ContextMenu>

Finally, here¡¯s the ListBox:

<ListBox Name="listBox1" ItemsSource="{Binding}" DisplayMemberPath="Name"/>






Re: Adaptive context menus

AdamCKing

Hi,

I need to do a very similar thing to the OP, but what you have suggested seems like a lot of work to simply add a context menu to every item Is it really not possible to do this in XAML in the item template If this is the case I should hope the ability appears in later releases, since surely it is a very common thing to want to do !

Also, I was under the impression that Items and ItemsSource were mutually exclusive, and you couldn't use one if you were using the other Or does ItemsSource populate Items along the way






Re: Adaptive context menus

Yi-Lun Luo - MSFT

Yes, if you¡¯re using DataTemplate, you don¡¯t need to manually set the ContextMenu to each item in code. Something like this will do the trick:

<DataTemplate x:Key="dt">

<StackPanel ContextMenu="{StaticResource cm}" Width="{Binding ElementName=listBox1, Path=ActualWidth}">

<TextBlock Text="{Binding Path=Name}"/>

</StackPanel>

</DataTemplate>

If you set ItemsSource, you won¡¯t be able to manually add or remove items. You¡¯ll have to modify the ItemsSource instead.






Re: Adaptive context menus

Mattias K

Hi and thank you for your answer.

What if I would like to update the enabled/disabled state of the context menu item depending on the number of items selected in the list

I am thinking of a scenario like file renaming, where renaming only is possible when one item is selected. If more then one item is selected it shouldn't be possible to rename.





Re: Adaptive context menus

AdamCKing

It doesn't really help, but in your example above for file renaming - irrespective of how many items you have selected, surely you would only expect to rename the specific item you right clicked on





Re: Adaptive context menus

Mattias K

Well, according to the behaviour of e.g. the file explorer in Windows, the selection is kept (indifferent of the number of items selected) when right-clicking on an already selected item.

This means that the context menu has to adapt to this scenario by disable/hide the rename operation since it isn't allowed on multiple items.





Re: Adaptive context menus

Ben Carter - MSFT

You could look at using a RoutedCommand on the MenuItem and then implementing CanExecute and Executed event handlers on the ListBox. The RoutedCommand will enable/disable the MenuItem automatically based on the result of CanExecute. In your CanExecute event handler, return true if only one item is selected. Otherwise, return false. The return value is on the event handler (e.CanExecute, I believe).

Ben






Re: Adaptive context menus

Mattias K

Thanks!

Routed commands seems to be the answer.