从ContentControl内的按钮触发命令?

3
我是WPF的新手,尝试在ContentControl中动态添加一个按钮,并在点击时触发命令。我正在使用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");
        }
    }

1
绑定的代理可能会有所帮助。请参见https://dev59.com/LWsz5IYBdhLWcg3wsaPN - dytori
2个回答

1
这里的问题在于ContentTemplate中的隐式DataContext是Content,而它还没有被设置为任何内容。您需要将Content设置为一些绑定,以桥接当前在可视树中的DataContext,例如:
<ContentControl ContentTemplate="{StaticResource MyButton}" Content="{Binding}"/>

我希望事情能够那么简单,但不幸的是,这并没有改变任何事情。 - Karmacon
@Karmacon 我所说的是正确的,如果对你不起作用,可能有其他问题,这些问题在你的问题中没有显示出来。 - King King
我在问题中包含了所有的代码并尝试了您的建议,但没有任何反应。 - Karmacon
@Karmacon,我刚刚亲自尝试了这段代码,它完美地运行了。你想让我发送一个演示项目吗? - King King
你能打开VS 2012项目吗?(需要至少VS 2012) - King King
让我们在聊天中继续这个讨论 - Karmacon

1

另一种解决方案是给你的窗口命名:

<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"/>

这对于像ListViews和ItemControls这样的东西特别方便,因为它们的DC被设置为列表元素。但请记住,这仅适用于同一可视树中的成员,如果不是这种情况(例如弹出菜单等),则需要代理绑定,如本文所述

谢谢!你的解决方案非常好,这篇文章很好地解释了发生了什么以及如何修复它。 - Karmacon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接