簡體   English   中英

將WPF窗口DataContext設置為RelativeSource Self

[英]Setting WPF Window DataContext to RelativeSource Self

如果我在構造函數中將Window的DataContext設置this以及在XAML 中將 {Binding RelativeSource={RelativeSource Self}}為I,那么我可以通過在其中放置一個斷點來看到DataContext引用了正確的對象實例(即MainWindow)。代碼隱藏的Loaded事件。 但是,Window的子元素exampleButton的Command綁定為null。 斷言失敗。

當我刪除XAML DataContext設置(僅依賴於構造函數設置)時,exampleButton的Command會正確使用DataContext。

為什么在XAML場景中exampleButton的Command綁定為null?

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

InitializeComponent之前設置ExampleCommandDataContext

 DataContext = this;
 ExampleCommand = new DelegateCommand(x => { throw new ApplicationException(); });
 InitializeComponent();

還要注意,使用DataContext="{Binding RelativeSource={RelativeSource Self}}"DataContext = this;沒有區別DataContext = this; ,如果您在initializecomponent之前設置了datacontext。

為什么在XAML場景中exampleButton的Command綁定為null?

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM