我正在對多個ViewModel進行反序列化,但是當它們發生變化時,視圖中的視覺控制元件(即TextBlock)卻沒有發生變化。在嘗試了問題的根源后,實際的反序列化并不是問題,但它是我的動機,為什么在另一個ViewModel中會有一個ViewModel。
關鍵的區別在于,改變的不僅僅是 VM 中的一個屬性,整個 ViewModel 正在改變(作為反序列化的結果)。
下面的代碼是一個簡化的示例,以顯示該問題。
MainWindow.xaml - Bound TextBlock and button
<StackPanel Orientation="Vertical">
<TextBlock x: Name="Test" FontSize="22" Text="{binding ExampleText}"/>
<Button x: Name="ButtonTest" FontSize="22" Width="100" Content="Load new VM" Click="LoadNewVM"/>
</StackPanel>/span>
主視窗背后的代碼
public partial class MainWindow : Windowpublic MainWindow()
{
InitializeComponent()。
//創建ExampleViewModel的新實體并加載到Singleton類MainWindowViewModel。
MainWindowViewModel.Instance.ExampleViewModel = new ExampleViewModel()。
//將資料背景關系設定為支持NotifyPropertyChanged的這個Singleton實體。
this.DataContext = MainWindowViewModel.Instance.ExampleViewModel。
}
//button click event, loads a new ViewModel into the Singleton class MainWindowViewModel with different text.
private void LoadNewVM(>object sender, RoutedEventArgs e)。
{
ExampleViewModel test = new ExampleViewModel()。
test.exampleText = "New Text"。
MainWindowViewModel.Instance.ExampleViewModel = test;
}
MainWindowViewModel - 為了確保我沒有把ViewModel搞混,我把它變成了一個Singleton。但還是不行。請注意,這個ViewModel包括ExampleViewModel實體。
class MainWindowViewModel。INotifyPropertyChanged
{
#region ExampleViewModel
private ExampleViewModel exampleViewModel。
public ExampleViewModel ExampleViewModel
{
get { return this.exampleViewModel; }
set
{
if (this.exampleViewModel !=value)
{
this.exampleViewModel = value;
NotifyPropertyChanged()。
}
}
}
#endregion
#region Make class singleton
private static readonly MainWindowViewModel instance = new MainWindowViewModel() 。
/tell c# compiler not to mark type as beforefieldinit
static MainWindowViewModel()
{
}
private MainWindowViewModel()
{
}
public static MainWindowViewModel Instance
{
get { return instance; }
}
#endregion
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged。
private void NotifyPropertyChanged([CallerMemberName] string PropertyName = ")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName))。
}
#endregion。
}
ExampleViewModel - 為了簡潔起見,我省略了NotifyPropertyChanged,但它是在類中。
class ExampleViewModel : INotifyPropertyChanged
{
public ExampleViewModel()
{
ExampleText = "初始文本"。
}
private string exampleText;
public string ExampleText
{
get { return exampleText; }
set
{
if (exampleText != value)
{
exampleText = value;
NotifyPropertyChanged();
MessageBox.Show("example Text is changing to " exampleText);
}
}
}
}
當我運行這個程式時,TextBlock最初顯示的是 "Initial Text",這符合預期。然后當我按下按鈕時,它呼叫LoadNewVM方法,將文本改為 "新文本"。然而,視覺控制并沒有改變。我甚至在ExampleText的Property setter中放了一個MessageBox,它確實顯示了文本正在改變為 "New Text"。但視圖中的TextBlock卻沒有變化。如果有任何幫助,我們將不勝感激。
uj5u.com熱心網友回復:
你沒有創建一個系結到DataContext屬性,而是從MainWindowViewModel.Instance.ExampleViewModel屬性分配了一個物件參考。
然后你改變了MainWindowViewModel.Instance.ExampleViewModel屬性的值,但是由于沒有系結,DataContext不能 "發現 "它。
下面的代碼可以幫助你理解問題的實質。
//set the data context to this Singleton instance which does support NotifyPropertyChanged
this.DataContext = MainWindowViewModel.Instance /*.ExampleViewModel */;
< StackPanel Orientation="Vertical" DataContext="{binding ExampleViewModel}">
<TextBlock x: Name="Test" FontSize="22" Text="{binding ExampleText}"/>
<Button x: Name="ButtonTest" FontSize="22" Width="100" Content="Load new VM" Click="LoadNewVM"/>
</StackPanel>/span>
值分配可以在XAML中完成。 這比用相當無用的代碼多載視窗后面的代碼要好。
<Window -------------
-------------
DataContext="{Binding ExampleViewModel, Source={x:Static local:MainWindowViewModel.Instance}}"/span>>
有了這個賦值,就不再需要設定StackPanel.DataContext。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/307894.html
標籤:
