从 ContentControl 中的按钮触发命令?

Fire a command from a Button inside a ContentControl?

我是 WPF 的新手,我正在尝试在 ContentControl 中动态添加一个 Button,它应该在单击时触发一个命令。我正在使用 MVVMLight 来处理命令。

下面我有一个有两个按钮的例子。顶部按钮直接放置在 StackPanel 中。此按钮按预期触发命令。

第二个按钮放置在 ContentControl 中。它显示正确,但单击按钮时命令不会触发。 我认为这是因为绑定不会通过 DataTemplate 向下传输,但如果我使用常规命令而不是 MVVMLight RelayCommands,它似乎可以工作。

我不想删除框架,所以我想知道是否有人知道如何修复它?谢谢

<Window x:Class="ContentControlExample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:ContentControlExample.ViewModel">

    <Window.DataContext>
        <vm:MainViewModel />
    </Window.DataContext>

    <Window.Resources>
        <DataTemplate x:Key="MyButton" >
            <Button Content="SUBMIT" Command="{Binding MyCommand}" Width="200" Height="50"/>
        </DataTemplate>
    </Window.Resources>

    <StackPanel>

        <!--When this button is clicked, the Command executes as expected-->
        <Button Content="SUBMIT" Command="{Binding MyCommand}" Width="200" Height="50"/>


        <!--Nothing happens when this button is clicked-->
        <ContentControl ContentTemplate="{StaticResource MyButton}"/>
    </StackPanel>
</Window>

这是带有命令的 ViewModel:

public class MainViewModel : ViewModelBase
{
        public ICommand MyCommand { get; private set; }

        public MainViewModel()
        {
            MyCommand = new RelayCommand(MyCommand_Executed, MyCommand_CanExecute);
        }

        private bool MyCommand_CanExecute()
        {
            return true;
        }

        private void MyCommand_Executed()
        {
            MessageBox.Show("The command executed");
        }
    }

这里的问题是 ContentTemplate 中的隐式 DataContext 是 Content 并且尚未设置任何内容。您需要将 Content 设置为一些 Binding 以桥接当前在可视化树中的 DataContext,如下所示:

<ContentControl ContentTemplate="{StaticResource MyButton}" Content="{Binding}"/>

另一个解决方案是给你的 Window 起个名字:

<Window x:Class="ContentControlExample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:ContentControlExample.ViewModel"
    x:Name="_this">

然后通过其上下文绑定:

<Button Content="SUBMIT" Command="{Binding ElementName=_this, Path=DataContext.MyCommand}" Width="200" Height="50"/>

这对于 ListView 和 ItemControl 之类的东西特别方便,因为它们的 DC 被设置为列表元素。请记住,这仅适用于同一可视树中的成员,如果不是这种情况(例如弹出菜单等),则您需要代理绑定 as described in this article.