开发者

ContextMenu bound to ObservableCollection<MenuItem> does not refresh data

开发者 https://www.devze.com 2023-02-07 23:00 出处:网络
Given the following XAML snippet: <UserControl.Resources> <ResourceDictionary> <Style x:Key=\"ContextMenuItemStyle\">

Given the following XAML snippet:

<UserControl.Resources>
    <ResourceDictionary>
        <Style x:Key="ContextMenuItemStyle">
            <Setter Property="MenuItem.Header" Value="{Binding Text}"/>
            <Setter Property="MenuItem.ItemsSource" Value="{Binding 开发者_StackOverflow中文版Children}"/>
            <Setter Property="MenuItem.Command" Value="{Binding Command}" />
        </Style>
       <ContextMenu x:Key="contextMenu" ItemsSource="{Binding MenuOptions}" ItemContainerStyle="{StaticResource ContextMenuItemStyle}" />
    </ResourceDictionary>
</UserControl.Resources>
<DockPanel>
    <TextBox Height="30" DockPanel.Dock="Top" ContextMenu="{StaticResource contextMenu}" />
    <Button Content="Add Menu Item" DockPanel.Dock="Top" Command="{Binding AddMenuItem}" />
 </DockPanel>

And View Model:

public class MyViewModel {

    public ObservableCollection<MenuItem> DocumentExplorerMenuOptions { get; set; }
    MenuItem firstMenuItem;
    MenuItem secondMenuItem;

    public MyViewModel() {
      firstMenuItem = new MenuItem("First") { Command = new DelegatingCommand(x => MessageBox.Show("First Selected") };
      secondMenuItem = new MenuItem("Second") { Command = new DelegatingCommand(x => MessageBox.Show("Second Selected") };

      MenuOptions = new ObservableCollection<MenuItem> { firstMenuItem, secondMenuItem };
      AddMenuItem = new DelegateCommand<object>(x => firstMenuItem.Children.Add(
            new MenuItem("Child of First")));

    }
    public DelegateCommand<object> AddMenuItem { get; set; }
}

And class:

public class MenuItem {
        public MenuItem(string text) {
            Text = text;
            Children = new List<MenuItem>();
        }
        public string Text { get; set; }
        public List<MenuItem> Children { get; private set; }
        public ICommand Command { get; set; }
    }

Clicking the button does add the child to firstMenuItem but it does not appear in the context menu of the TextBox.

I can't figure out how to make the context menu show the dynamic content of the context menu. Any thoughts?


I would not bind to a collection of MenuItems but rather to a more data-driven collection which may contain the MenuItem header, a command which is executed upon click and another collection of such items for the sub-items. Then you could use a (Hierarchical)DataTemplate to generate the menu on the fly. Doing so would probably take care of update issues if your datatype implements the necessary interfaces.

Edit: You seem to have such a datatype already, could you post its code?

Edit2: I think the problem is that you use a style that explicitly needs to be applied (it is probably only being applied to the main context menu, not the sub-items), as noted before i'd suggest a HierarchicalDataTemplate.

Edit3: lol...

public List<MenuItem> Children { get; private set; }

Of course it's not going to update if it's a List and not an ObservableCollection.

(The class is quite badly designed overall by the way, Lists should normally not even have a private setter, they should be properties with just a getter to a readonly field)

0

精彩评论

暂无评论...
验证码 换一张
取 消