如果我在构造函数中将Window的DataContext设置为this
以及在XAML中将设置为{Binding RelativeSource={RelativeSource Self}}
,那么我可以看到DataContext引用了通过在代码隐藏的Loaded事件中放置一个断点来正确的对象实例(即MainWindow)。但是,Window的子元素exampleButton的Command绑定为null。断言失败了。
当我删除XAML DataContext设置(并且仅依赖于构造函数设置)时,exampleButton的命令正确使用DataContext。
为什么exampleButton的命令在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
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
}
}
答案 0 :(得分:2)
在<add name="xyz" connectionString="Data Source=IP ADDRESS;Initial Catalog=DBNAME;User ID=USERNAME;Password=PASS;Integrated Security=False" providerName="System.Data.SqlClient" />
之前设置ExampleCommand
和DataContext
:
InitializeComponent
另请注意,如果在initializecomponent之前设置datacontext,则使用 DataContext = this;
ExampleCommand = new DelegateCommand(x => { throw new ApplicationException(); });
InitializeComponent();
或DataContext="{Binding RelativeSource={RelativeSource Self}}"
之间没有区别。
答案 1 :(得分:2)
为什么exampleButton的命令在XAML场景中绑定为空?
因为在ExampleCommand
方法返回并且设置了InitializeComponent()
属性时,DataContext
属性实际上具有null值。
如果要在此之后将属性设置为新值,则该类必须实现目标属性的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));
}
}