在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>
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");
}
}
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>
用户控制代码
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
}
答案 0 :(得分: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>
其他解决方案:
您忘了将 DataContext 设置为 UserControl1 。
public UserControl1()
{
InitializeComponent();
ClickHereCommand = new RoutedCommand();
CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));
ButtonContent = "Click Here";
this.DataContext = this;
}
在此之后,您必须删除Grid中的 UserControl1 DataContext。
此:
<Grid DataContext="{Binding ElementName=root}" >
<Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
</Grid>
你必须改为:
<Grid>
<Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90"></Button>
</Grid>
在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));
在UserControl1
的代理商中:
public UserControl1()
{
InitializeComponent();
ClickHereCommand = new RoutedCommand();
CommandBindings.Add(new CommandBinding(ClickHereCommand, ClickHereExecuted));
ButtonContent = "Click Here";
//this.DataContext = this;
}
答案 1 :(得分: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>
解决方案是使用相对源来设置数据上下文,如下所示:
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}" >
<Button Content="{Binding ButtonContent}" Command="{Binding ClickHereCommand}" Height="25" Width="90">
</Button>
</Grid>
我问过的问题的唯一答案是上面的问题(事实上可能有其他答案,但到目前为止这个问题还没有讨论过)。 特别: 在usercontrol中设置“DataContext = this”不是解决方案,实际上会破坏托管用户控件的控件中的绑定。 此外,只有作为绑定目标的属性必须是依赖项属性。这个建议是不正确的。