簡體   English   中英

在構造函數中設置DataContext = this和在WPF中綁定到{RelativeSource Self}之間的區別?

[英]Difference between setting DataContext=this in constructor and Binding to {RelativeSource Self} in WPF?

下一個代碼按預期工作:

AskWindow.xaml:

<Window
    x:Class='AskWPF.AskWindow'
    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
    xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
    >

<DataGrid ItemsSource="{Binding SimpleItems}" />

</Window>

AskWindow.xaml.cs:

namespace AskWPF {

public class SimpleRow {
    private string firstColumn;
    private string secondColumn;

    public SimpleRow(string first, string second) {
        firstColumn = first;
        secondColumn = second;
    }

    public string FirstColumn {
        get { return firstColumn; }
        set { firstColumn = value; }
    }

    public string SecondColumn {
        get { return secondColumn; }
        set { secondColumn = value; }
    }
}

public partial class AskWindow : Window {

    private ObservableCollection<SimpleRow> simpleItems;

    public AskWindow() {
        InitializeComponent();
        DataContext = this;

        simpleItems = new ObservableCollection<SimpleRow>();
        simpleItems.Add(new SimpleRow("row 0, column 0", "row 0, column 1"));
        simpleItems.Add(new SimpleRow("row 1, column 0", "row 1, column 1"));
    }

    public ObservableCollection<SimpleRow> SimpleItems {
        get { return simpleItems; }
    }
}

}

但是,如果在Window標記中設置DataContext='{Binding RelativeSource={RelativeSource Self}}' ,並在注釋行DataContext=this得到一個空窗口。 為什么?

AskWindow.xaml:

<Window .... DataContext='{Binding RelativeSource={RelativeSource Self}}'>

    <DataGrid ItemsSource="{Binding SimpleItems}" />

</Window>

AskWindow.xaml.cs:

...
public AskWindow() {
    InitializeComponent();
    // DataContext = this;

    simpleItems = new ObservableCollection<SimpleRow>();
    simpleItems.Add(new SimpleRow("row 0, column 0", "row 0, column 1"));
    simpleItems.Add(new SimpleRow("row 1, column 0", "row 1, column 1"));
}
...

我懷疑這與評估某些種類的綁定的方式和時間有關。 在后一種情況下,我認為綁定可以在仍為null的情況下檢索collection屬性的值,然后更改屬性(通過設置字段),而不會觸發受影響屬性的任何更改通知。

建議將InitializeComponent調用移到構造函數的末尾,或者至少預先設置字段。

通常我使用一個只讀字段,並立即對其進行初始化:

private readonly ObservableCollection<Data> collection =
    new ObservableCollection<Data>();
public ObservableCollection<Data> Collection { get { return collection ; } }

這是我的猜測。 在兩種情況下,您的Collection都為空。 確切地說,在InitializeComponent之后。 此時,初始數據綁定獲得了數據,但沒有數據上下文。 現在,通過設置DataContext,可以引發屬性以及與之相關的每個綁定,並使其無效和刷新。 這是我的猜測部分,它起作用的原因是推遲了對ItemsSource的綁定,因此它只能在下一行中設置集合。

簡而言之:設置Datacontext將重新觸發綁定。 但是在您的RelativeSource示例中,綁定從一開始就起作用,但是集合為null,並且您從未告訴過wpf重新獲取綁定。 如果您直接初始化集合,它應該可以正常工作。

實際上,綁定是正確的,並且也可以使用。 為了更新屏幕,綁定必須接收有關某些更改的通知。 綁定首先評估,然后偵聽通知。 在第二個版本中,綁定首先評估何時運行InitializeComponent,但是此時沒有任何值,因此您什么也看不到。 此后,將創建值,但不會重新評估綁定,因為不會發送任何通知。

因此,一種解決方案是在InitializeComponent之前初始化集合。

...
private ObservableCollection<SimpleRow> simpleItems = new ObservableCollection<SimpleRow>();
...

另一個解決方案是愚蠢的,並且過高地通知綁定已更改某些內容。

請注意,這可能是出於學習目的,因為UI不應與模型混淆。

暫無
暫無

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

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