[英]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.