【问题标题】:How do I properly bind my ContextMenu command to a RelayCommand?如何正确地将 ContextMenu 命令绑定到 RelayCommand?
【发布时间】:2018-11-11 05:07:29
【问题描述】:

所以我在RelayCommand 上设置了几个按钮,它运行良好,但是当尝试绑定ContextMenu Menu ItemCommand 属性时,它只是没有反应。 我读过一些关于必须设置级别的 AncestorType 或其他内容的内容,但这是一个非常庞大的描述,没有解释为什么或如何。

所以我有我的 ListView

<ListView x:Name="PlayerListView"
                  Width="200"
                  Height="330"
                  VerticalAlignment="Top"
                  Margin="0,80,15,0"
                  HorizontalAlignment="Right"
                  Background="#252525"
                  VerticalContentAlignment="Center"
                  ItemsSource="{Binding ServerViewModel.Players}">

            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" 
                                VerticalAlignment="Stretch" 
                                HorizontalAlignment="Stretch"
                                Width="190"
                                Background="#222222">

                        <StackPanel.ContextMenu>
                            <ContextMenu>
                                <MenuItem Header="Command One">
                                    <MenuItem.Icon>
                                        <Image Source="../../Assets/image.png"
                                               RenderOptions.BitmapScalingMode="Fant"/>
                                    </MenuItem.Icon>
                                </MenuItem>

                                <MenuItem Header="Command Two"
                                          Command="{Binding ServerViewModel.MyCommand,
                                    RelativeSource={RelativeSource AncestorType=ListViewItem}}">
                                    <MenuItem.Icon>
                                        <Image Source="../../Assets/image.png"
                                               RenderOptions.BitmapScalingMode="Fant"/>
                                    </MenuItem.Icon>
                                </MenuItem>
                            </ContextMenu>
                        </StackPanel.ContextMenu>

                        <Image Source="../../Assets/image.png"
                               Width="20"
                               Height="20"/>

                        <TextBlock Text="{Binding Username}" 
                                   Foreground="White"
                                   HorizontalAlignment="Stretch"
                                   VerticalAlignment="Center" 
                                   Margin="5"/>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

正如您在第二个项目中看到的那样,我正在尝试将其绑定到我的 RelayCommand。 它应该可以工作,因为我的按钮已正确设置了视图模型和数据上下文。

public class BaseViewModel : ObservableObject
    {
        public ServerViewModel ServerViewModel { get; set; } = new ServerViewModel();
    }

视图模型

public RelayCommand MyCommand { get; set; }

public ServerViewModel()
        {
            MyCommand = new RelayCommand(DoSomething);
        }
public void DoSomething(object parameter)
        {
            MessageBox.Show("Working!");
        }

当然还有 RelayCommand 本身。 RelayCommands 再次适用于按钮,但不适用于 ContextMenu 项

public class RelayCommand : ObservableObject, ICommand
    {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }

        public RelayCommand(Action<object> execute) : this(execute, null)
        {

        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            _execute.Invoke(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }

这是我设置 DataContext 的地方

public MainWindow()
        {
            InitializeComponent();
            DataContext = new BaseViewModel();
        }

【问题讨论】:

  • 据我所知ContextMenus 不是可视化树的一部分,因此它们不会继承父控件的DataContext。您使用RelativeSource 的方法应该可以解决问题。但是您当前的代码将绑定的源定义为ListViewItem,但ListViewItems 没有要绑定的属性ServerViewModel,或者是吗?尝试绑定到DataContext.ServerViewModel.MyCommand
  • 似乎没有任何改变

标签: c# .net wpf mvvm contextmenu


【解决方案1】:

这段代码

Command="{Binding ServerViewModel.MyCommand, RelativeSource={RelativeSource AncestorType=ListViewItem}}"

尝试在 ListViewItem 类中查找属性 ServerViewModel 却找不到。 如果 ServerViewModel.Players 返回的对象本身就是 ViewModel 对象,您可以删除 RelativeSource 部分并将您的命令添加到 Player ViewModel。

例子:

Command="{Binding MyCommand}"

在 PlayerViewModel 中:

    public RelayCommand MyCommand { get; set; }

    public PlayerViewModel()
    {
        MyCommand = new RelayCommand(DoSomething);
    }
    public void DoSomething(object parameter)
    {
        MessageBox.Show("Player Working!");
    }

有关替代解决方案,请参阅此处:WPF: Binding a ContextMenu to an MVVM Command

【讨论】:

  • 似乎没有任何改变
猜你喜欢
  • 2020-03-10
  • 2015-03-13
  • 2016-07-02
  • 1970-01-01
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多