INotifyPropertyChanged 混乱

INotifyPropertyChange confusion

我正在将 VB.NET Winforms 项目转换为 C# WPF。

我有一个包含两个 WPF windows 和一个 ViewModel 作为引用项目的项目。

public class SheepViewModel : INotifyPropertyChanged
{
    
    private string _CurrentEventName;
public string CurrentEventName
{
    get { return _CurrentEventName; }
        set
            {
              _CurrentEventName = value;
              OnPropertyChanged("CurrentEventName");
            }
    }
    
    static SheepViewModel _details;
    public static SheepViewModel GetDetails()
    {
        if (_details == null)
            _details = new SheepViewModel();
        return _details;
    }

    public event PropertyChangedEventHandler PropertyChanged;
  
    private void OnPropertyChanged(string prop)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
            Console.WriteLine(prop + " has changed");
    }
   }

我显示东西的 window 看起来像这样。

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:SheepViewModel;assembly=SheepViewModel"
        xmlns:ShaderEffectLibrary="clr-namespace:ShaderEffectLibrary;assembly=ShaderEffectLibrary" x:Class="Sheep_Score_3._1.ScoreScreen"
        mc:Ignorable="d"
        Title="ScoreScreen" Height="540" Width="920" WindowStartupLocation="CenterScreen">
    <Window.DataContext>
        <vm:SheepViewModel/>
    </Window.DataContext>
    
    <Viewbox x:Name="Stand1ViewBox" RenderTransformOrigin="0.5,0.5">
    <Canvas x:Name="StandViewBox" Height="112.513" Margin="0,1100,2,0" VerticalAlignment="Bottom" RenderTransformOrigin="0.493,0.473" Background="#FF999999" Width="2268">
        <TextBlock x:Name="CurrentEventName" Canvas.Left="270.9" TextWrapping="Wrap" Width="1104.815" FontFamily="Calibri" FontSize="29.333" FontStyle="Italic" Canvas.Top="-1.649" Text="{Binding Path=CurrentEventName}"/>
        </Canvas>
    </Viewbox>
</Window>   

My MainWindow which is a control window looks like this
```xaml
<Window x:Class="Sheep_Score_3._1.MainWindow"
        xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:SheepViewModel;assembly=SheepViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="433.689" Width="941.194">
    <Window.DataContext>
        <vm:SheepViewModel/>
    </Window.DataContext>
        <Grid Margin="0,0,0,0">
            <TextBox x:Name="CurrentEventName" Height="23" Margin="131.01,163.013,0,0" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalAlignment="Left" Width="327.151" Text="{Binding CurrentEventName, Mode=TwoWay}"/>
    </Grid>
</Window>           

如果我在控件 window 文本框中键入内容,它会显示在文本块中 window 上,因此我的绑定正在工作,我可以看到 INotifyPropertyChanged.PropertyChanged 事件上调。一切都很好。

但是,如果我以编程方式更改 属性,我仍然可以看到引发的 INotifyPropertyChanged.PropertyChanged 事件,但文本框和文本块不会更新为新值。

SheepViewModel.SheepViewModel.GetDetails().CurrentEventName = "This is the new value";

我是不是漏掉了什么?

我真的很惊讶文本更新对你有用;它绝对不在我身边。原因如下:

您在两个 windows 中都有以下代码段:

<Window.DataContext>
    <vm:SheepViewModel/>
</Window.DataContext>

这基本上是说:创建一个新的 SheepViewModel 实例并将其设置为 window 的数据上下文。由于您在两个 windows 中都有这个,每个 window 将有一个单独的 ViewModel 实例。由于 CurrentEventName 属性 是一个实例 属性,该值不会在实例之间共享,也不会正确更新。

当您尝试以编程方式更新值时,您调用 SheepViewModel.GetDetails()。这会创建另一个实例,与控件使用的实例完全无关。因此,您看不到任何更新。

你想要的是以上所有使用一个视图模型实例。为此,您可以从后面的代码中设置 windows 的 DataContext。您可以在 windows:

中使用以下构造函数,而不是使用上面的 XAML 代码段
public DisplayWindow()
{
    InitializeComponent();
    this.DataContext = SheepViewModel.GetDetails();
}

这确保 windows 引用通过 GetDetails 方法检索的单例实例。

为了保证您的 windows 共享相同的视图模型,请删除 Steven 记录的片段并在您的 windows 的构造函数中调用以下代码:

DataContext = SheepViewModel.GetDetails();