INotifyPropertyChange混乱 [英] INotifyPropertyChange confusion

查看:45
本文介绍了INotifyPropertyChange混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am converting a VB.NET Winforms project to C# WPF.

我有一个带有两个WPF窗口和一个ViewModel作为参考项目的项目.

I have a project with two WPF windows and a ViewModel as a referenced project.

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");
    }
   }

我显示事物的窗口看起来像这样.

The window where I display things looks like this.

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

如果我在控制窗口文本框中键入内容,它将出现在文本块的显示窗口中,因此我的绑定正在工作,并且我可以看到引发的 INotifyPropertyChanged.PropertyChanged 事件.一切都很好.

If I type something into the control window text box it appears on the display window in the text block, so my bindings are working and I can see the INotifyPropertyChanged.PropertyChanged event raised. That's all working great.

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

However, if I change the property programmatically, I can still see the INotifyPropertyChanged.PropertyChanged event raised, but the text box and text block do not update with the new value.

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

我在这里想念东西吗?

推荐答案

我实际上对文本更新对您有用感到惊讶.它绝对不在我这边.原因如下:

I'm actually surprised that the text updates work for you; it definitely doesn't on my side. Here's why:

两个窗口中都有以下代码段:

You have the following snippet in both windows:

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

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

This basically says: create a new instance of SheepViewModel and set it as the window's datacontext. Since you have this in both windows, each window will have a separate instance of the ViewModel. As the CurrentEventName property is an instance property, the value won't be shared between the instances and won't update properly.

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

When you try to programmatically update the value, you call SheepViewModel.GetDetails(). This creates yet another instance, totally unrelated to the ones used by the controls. Therefore, you don't see any updates.

您想要的就是以上所有这些,以使用一个单独的viewmodel实例.为此,您可以从后面的代码中设置窗口的DataContext.除了使用上面的XAML代码段,您还可以在Windows中使用以下构造函数:

What you want is all of the above to use one single viewmodel instance. To do this, you can set the DataContext of the windows from code behind. Instead of using above XAML snippet, you can use following constructor in your windows:

public DisplayWindow()
{
    InitializeComponent();
    this.DataContext = SheepViewModel.GetDetails();
}

这确保窗口引用通过 GetDetails 方法检索的单例实例.

This ensures that the windows refer to the singleton instance that is retrieved through the GetDetails method.

这篇关于INotifyPropertyChange混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆