如何在wpf中的用户控件中使用命令绑定?

Sam*_*Sam 8 .net c# wpf

在MainWindow中,命令绑定工作正常.在UserControl1中它不起作用.请注意,datacontext设置正确,因为按钮的内容是绑定的结果.

我不是试图将usercontrol中的命令绑定到mainwindow中的命令或任何其他此类欺骗.我只是想在UserControl1中复制我在MainWindow中所做的事情.

MainWindow XAML

<StackPanel>
    <Button Content="Click Here" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
    <local:UserControl1></local:UserControl1>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

MainWindow代码背后

public partial class MainWindow : Window
{
    public static RoutedCommand ClickHereCommand { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
        ClickHereCommand = new RoutedCommand();
        CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));
    }

    public void ClickHereExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        System.Windows.MessageBox.Show("hello");
    }
}
Run Code Online (Sandbox Code Playgroud)

UserControl XAML

<UserControl x:Class="CommandBindingTest.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300" x:Name="root">

<Grid DataContext="{Binding ElementName=root}" >
    <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

UserControl代码背后

public partial class UserControl1 : UserControl, INotifyPropertyChanged
{
    private string _ButtonContent;
    public string ButtonContent
    {
        get { return _ButtonContent; }
        set
        {
            if (_ButtonContent != value)
            {
                _ButtonContent = value;
                OnPropertyChanged("ButtonContent");
            }
        }
    }

    public static RoutedCommand ClickHereCommand { get; set; }


    public UserControl1()
    {
        InitializeComponent();
        ClickHereCommand = new RoutedCommand();
        CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));
        ButtonContent = "Click Here";
    }

    public void ClickHereExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        System.Windows.MessageBox.Show("hello from UserControl1");
    }


    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

kma*_*zek 13

这是最好的解决方案:

 <Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" >
        <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
 </Grid>
Run Code Online (Sandbox Code Playgroud)

其他方案:

您忘记将DataContext设置为UserControl1.

  public UserControl1()
        {
            InitializeComponent();
            ClickHereCommand = new RoutedCommand();
            CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));
            ButtonContent = "Click Here";
            this.DataContext = this;
        }
Run Code Online (Sandbox Code Playgroud)

在此之后,您必须删除Grid 中的UserControl1 DataContext.

这个:

<Grid DataContext="{Binding ElementName=root}" >
    <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
</Grid>
Run Code Online (Sandbox Code Playgroud)

你必须改变这个:

<Grid>
        <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
</Grid>
Run Code Online (Sandbox Code Playgroud)

在UserControl中没有设置DataContext的解决方案:

您必须将ButtonContent和ClickHereCommand更改为DependencyProperty.

        public string ButtonContent
        {
            get { return (string)GetValue(ButtonContentProperty); }
            set { SetValue(ButtonContentProperty, value); }
        }

        public static readonly DependencyProperty ButtonContentProperty =
            DependencyProperty.Register("ButtonContent", typeof(string), typeof(UserControl1), new UIPropertyMetadata(string.Empty));

        public RoutedCommand ClickHereCommand
        {
            get { return (RoutedCommand)GetValue(ClickHereCommandProperty); }
            set { SetValue(ClickHereCommandProperty, value); }
        }

        public static readonly DependencyProperty ClickHereCommandProperty =
            DependencyProperty.Register("ClickHereCommand", typeof(RoutedCommand), typeof(UserControl1), new UIPropertyMetadata(null));
Run Code Online (Sandbox Code Playgroud)

并在以下情况下UserControl1:

 public UserControl1()
    {
        InitializeComponent();

        ClickHereCommand = new RoutedCommand();
        CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));            
        ButtonContent = "Click Here";
        //this.DataContext = this;
    }
Run Code Online (Sandbox Code Playgroud)


Sam*_*Sam 11

在我发布这篇文章差不多两年后,我才重新开始.我忘记了WPF的这个小功能,果然它再次让我感到困惑.

上面标记的答案部分正确,但包含其他令人分心和/或不正确的内容.为清楚起见,我将重点介绍问题所在以及解决方案的内容.为了我的利益,我这样做比你的更多,因为我相信我会在大约十六个月后回到这里.

这是问题所在.不要这样做.除了路由命令之外,您的绑定都将继续有效:

<UserControl x:Class="CommandBindingTest.UserControl1"
     // snip
     d:DesignHeight="300" d:DesignWidth="300" x:Name="root">

    <Grid DataContext="{Binding ElementName=root}" >
        <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90">
        </Button>
    </Grid>
Run Code Online (Sandbox Code Playgroud)

解决方案是使用相对源来设置数据上下文,如下所示:

<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" >
    <Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90">
    </Button>
</Grid>
Run Code Online (Sandbox Code Playgroud)

以我问这个问题的唯一答案是上面的一个(有可能实际上是其他的答案,但他们没有在这个问题上目前所讨论).具体来说:在usercontrol中设置"DataContext = this"不是解决方案,实际上会破坏托管用户控件的控件中的绑定.此外,只有作为绑定目标的属性必须是依赖项属性.这个建议是不正确的.