WPF DataBinding未使用INotifyPropertyChanged进行更新

时间:2017-08-01 15:12:20

标签: c# wpf xaml

我正在尝试为练习创建一个非常简单的数据绑定应用程序,但我无法让它工作,我看了很多不同的解决方案,但没有一个帮助,我无法弄清楚问题

MainWindow.xaml:

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

<Grid>
    <TextBlock Text="{Binding BindText, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

Window1.xaml:

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

<Grid>
    <TextBox Text="{Binding BindText, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

视图模型:

using System.ComponentModel;

namespace bindtest
{
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string bindText = "Hello";
        public string BindText
        {
            get { return bindText; }
            set
            {
                bindText = value;
                OnPropertyChanged("BindText");
            }
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

文本首次加载时会正确显示,但不会更新。 MainWindow中的文本用于在window1中的文本更改时进行更新。 有解决方案吗 感谢

2 个答案:

答案 0 :(得分:2)

正如JanDotNet建议的那样,您需要使用视图模型的单个实例。因此,在您的应用级代码中,您可以执行以下操作:

public partial class App : Application
{
    private void App_Startup(object sender, StartupEventArgs e)
    {
        try
        {
            ViewModel vm = new ViewModel();
            MainWindow w = new MainWindow(vm);
            Window1 w1 = new Window1(vm);
            w.Show();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

然后你的窗口构造函数修改如下:

public partial class MainWindow : Window
{
    pulic MainWindow(ViewModel vm)
    {
         InitializeComponent();
         DataContext = vm;
    }
}

答案 1 :(得分:1)

由于您是通过以下方式创建视图模型的:

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

您有2个不同的视图模型实例。您必须将视图模型的相同实例绑定到视图。

如何针对2个视图绑定同一个实例?

在您的情况下,最简单的方法是创建一个单身人士:

public class ViewModel : INotifyPropertyChanged
{
     public ViewModel Instance {get; } = new ViewModel();
     // ....
}

并绑定到它:

<Window DataContext="{Binding Source={x:Static local:ViewModel.Instance}}" /* ... */>

请注意,这不是最佳方式....

您应该使用PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

var handler = PropertyChanged;
if (handler != null) 
    handler(this, new PropertyChangedEventArgs(propertyName)

确保在检查null和调用事件处理程序之间没有取消订阅处理程序!