[英]Setting WPF Window DataContext to RelativeSource Self
If I set the Window's DataContext to this
in the constructor as well as to {Binding RelativeSource={RelativeSource Self}}
in XAML then I can see that the DataContext refers to the correct object instance (ie the MainWindow) by placing a break point in the code-behind's Loaded event. 如果我在构造函数中将Window的DataContext设置
this
, 以及在XAML 中将 {Binding RelativeSource={RelativeSource Self}}
为I,那么我可以通过在其中放置一个断点来看到DataContext引用了正确的对象实例(即MainWindow)。代码隐藏的Loaded事件。 However, the Window's child element exampleButton's Command binding is null. 但是,Window的子元素exampleButton的Command绑定为null。 The assertion fails.
断言失败。
When I remove the XAML DataContext setting (and rely on the constructor setting only) then exampleButton's Command uses the DataContext correctly. 当我删除XAML DataContext设置(仅依赖于构造函数设置)时,exampleButton的Command会正确使用DataContext。
Why is exampleButton's Command bound to null in the XAML scenario? 为什么在XAML场景中exampleButton的Command绑定为null?
MainWindow.xaml MainWindow.xaml
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Example"
SizeToContent="WidthAndHeight"
x:Name="mainWindow"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Loaded="mainWindow_Loaded">
<Button x:Name="exampleButton" Command="{Binding Path=ExampleCommand}" Content="Click"/>
</Window>
MainWindow.xaml.cs MainWindow.xaml.cs
public partial class MainWindow : Window
{
public ICommand ExampleCommand { get; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
ExampleCommand = new DelegateCommand(x => { throw new ApplicationException(); });
}
private void mainWindow_Loaded(object sender, RoutedEventArgs e)
{
Debug.Assert(mainWindow == this);
Debug.Assert(mainWindow.DataContext == this);
Debug.Assert(exampleButton.DataContext == this);
Debug.Assert(exampleButton.Command == ExampleCommand); //<-- FAIL
}
}
Set ExampleCommand
and DataContext
before InitializeComponent
: 在
InitializeComponent
之前设置ExampleCommand
和DataContext
:
DataContext = this;
ExampleCommand = new DelegateCommand(x => { throw new ApplicationException(); });
InitializeComponent();
Also note that there is no difference between using DataContext="{Binding RelativeSource={RelativeSource Self}}"
or DataContext = this;
还要注意,使用
DataContext="{Binding RelativeSource={RelativeSource Self}}"
或DataContext = this;
没有区别DataContext = this;
, if you set datacontext before initializecomponent. ,如果您在initializecomponent之前设置了datacontext。
Why is exampleButton's Command bound to null in the XAML scenario?
为什么在XAML场景中exampleButton的Command绑定为null?
Because the ExampleCommand
property actually has a value of null by the time the InitializeComponent()
method returns and the DataContext
property is set. 因为
ExampleCommand
属性在InitializeComponent()
方法返回并设置DataContext
属性时实际上具有null值。
If you want to set a property to a new value after this, the class must implement the INotifyPropertyChanged interface for the target property to get refreshed automatically: 如果要在此之后将属性设置为新值,则该类必须实现INotifyPropertyChanged接口,以使目标属性自动刷新:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
ExampleCommand = new RelayCommand<object>(x => { throw new ApplicationException(); });
}
private ICommand _exampleCommand;
public ICommand ExampleCommand
{
get { return _exampleCommand; }
set { _exampleCommand = value; NotifyPropertyChanged(); }
}
private void mainWindow_Loaded(object sender, RoutedEventArgs e)
{
Debug.Assert(exampleButton.DataContext == this);
Debug.Assert(exampleButton.Command == ExampleCommand); //<-- FAIL
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.