C#WPF InotifyPropertyChange混乱

时间:2016-02-03 01:15:08

标签: c# wpf xaml binding

我正在将VBnet winforms项目转换为C#WPF。两者都是新的,所以试图弄明白。

我有一个项目有两个WPF窗口和一个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
    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>

我的MainWindow是一个控制窗口,如下所示

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

现在,如果我在控制窗口文本框中输入内容,它会出现在文本块的“显示”窗口中,因此我的绑定正在运行,我可以看到NotifyProperyChange消息。这一切都很有效。

但是,如果我以编程方式更改属性,我仍然可以看到NotifyPropertyChange触发,但文本框和文本块不会使用新值更新。

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

我在这里遗漏了什么吗? 任何有关这方面的指导都会受到欢迎,我已经检查过我正在调用正确的地产名称并用Google搜索这几天,试图找出它,但我现在完全被卡住了。

2 个答案:

答案 0 :(得分:2)

我真的很惊讶文本更新对你有用;它肯定不在我身边。这就是原因:

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

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

这基本上说:创建一个SheepViewModel的新实例并将其设置为窗口的datacontext。由于在两个窗口中都有这个,因此每个窗口都有一个单独的ViewModel实例。由于CurrentEventName属性是一个实例属性,因此不会在实例之间共享该值,并且无法正确更新。

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

你想要的就是使用一个单一的viewmodel实例。为此,您可以从后面的代码设置窗口的DataContext。您可以在Windows中使用以下构造函数,而不是使用上面的XAML代码段:

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

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

答案 1 :(得分:1)

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

DataContext = SheepViewModel.GetDetails();