Databinding a command to Context Menu with an Observable Collection

感情迁移 提交于 2019-12-25 02:25:51

问题


I have a Context menu with some options. One of the options is an Observable collection and I am having issues binding my commands in my view model to them. I have seen many different ways to fix this issue, but none have worked because they do not specifically relate to my problem. Here is my code first:

XAML:

 <ListView ItemsSource="{Binding ListViewItems}" SelectionMode="Single">
            <ListView.ContextMenu>
                <ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
                    <MenuItem Header="Test" Command="{Binding TestCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}" />
                    <Separator></Separator>
                    <MenuItem Header="Status" ItemsSource="{Binding DataContext.ObservableCollectionList}" DisplayMemberPath="Name" Command="{Binding Path=DataContext.UpdateCommand}" CommandParameter="{Binding Path=SelectedItem}"/>
                </ContextMenu>
            </ListView.ContextMenu>
//listviewstuff here
</ListView>

VM:

public class VM : ViewModelBase
{
    public RelayCommand UpdateCommand { get; private set; }
    public Action UpdateCommandAction { get; set; }
    public ObservableCollection<Status> ObservableCollectionList { get; set; }

    public VM()
    {
        this.UpdateCommand = new RelayCommand(new Action(() => this.UpdateCommandAction.DynamicInvoke())));
    }
}

Code-behind for the XAML view:

public partial class View
{
    public View()
    {
        InitializeComponent();
        var ViewDataContext = this.DataContext as VM;
        ViewDataContext .UpdateCommandAction = UpdateStatus;
    }


    private void UpdateStatus()
    {
        MessageBox.Show("test");
    }

}

I inserted a break point and it's not even making it to the method call. The debug output is not showing an error for me when I run the program either. What I don't understand is when I add this Command to the regular menu item that is NOT populated by a data bound list, it works fine. I would appreciate a fresh pair of eyes and some insight in to how this works.


回答1:


You need to bind the command to all the child items, now you bind it on the parent which will ignore it because it has child items (opens sub-menu instead).

To bind it on the children you need the ItemContainerStyle, create a Setter for the Command there. You will need to walk up again, probably this: {Binding DataContext.DataContext.UpdateCommand, RelativeSource={RelativeSource AncestorType=MenuItem}} (not sure about the AncestorLevel, if it does select itself instead of the parent increase it; double DataContext because you bound to DataContext.ObservableCollectionList, assuming that binding to actually work).

Likewise there is no SelectedItem in a menu, you need another Setter for CommandParameter, it will simply bind to the current item, i.e. {Binding}.


Edit: Code example:

<MenuItem Header="Status"
          ItemsSource="{Binding DataContext.ObservableCollectionList}"
          DisplayMemberPath="Name">
  <MenuItem.ItemContainerStyle>
    <Style TargetType="MenuItem">
      <Setter Property="Command" Value="{Binding DataContext.DataContext.UpdateCommand,
                                             RelativeSource={RelativeSource AncestorType=MenuItem}}"/>
      <Setter Property="CommandParameter" Value="{Binding}"/>
    </Style>
  </MenuItem.ItemContainerStyle>
</MenuItem>



回答2:


You'll need a List<MenuItem> MenuItems to bind with ContextMenu ItemSource property as

public class MenuItem
{
    public string Header { get; set; }

    public ICommand Command { get; set; }
}

XAML: and set itemContainerstyle

<ContextMenu ItemsSource="{Binding MenuItems}" >
        <ContextMenu.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}" >
                <Setter Property="Header" Value="{Binding Header}"/>
                <Setter Property="Command" Value="{Binding Command}" />
            </Style>
        </ContextMenu.ItemContainerStyle>
    </ContextMenu>

And add as many contextmenu item you want in your ViewModel AS YOU WANT.



来源:https://stackoverflow.com/questions/24875966/databinding-a-command-to-context-menu-with-an-observable-collection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!