将WPF窗口DataContext设置为RelativeSource Self

时间:2017-03-04 09:11:45

标签: c# wpf xaml

如果我在构造函数中将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
    }
}

2 个答案:

答案 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" /> 之前设置ExampleCommandDataContext

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));
    }
}