【问题标题】:PropertyChanged event always nullPropertyChanged 事件始终为空
【发布时间】:2010-12-03 12:20:06
【问题描述】:

我有以下(缩写)xaml:

<TextBlock Text="{Binding Path=statusMsg, UpdateSourceTrigger=PropertyChanged}"/>

我有一个单例类:

public class StatusMessage : INotifyPropertyChanged
{   
    private static StatusMessage instance = new StatusMessage();

    private StatusMessage() { }

    public static StatusMessage GetInstance()
    {
        return instance;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string status)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(status));
        }
    }

    private string statusMessage;
    public string statusMsg
    {
        get
        {
            return statusMessage;
        }
        set
        {
            statusMessage = value;
            OnPropertyChanged("statusMsg");
        }
    }
}

在我的主窗口构造函数中:

StatusMessage testMessage = StatusMessage.GetInstance();
testMessage.statusMsg = "This is a test msg";    

我无法让文本块显示测试消息。当我通过调试监控代码时,PropertyChanged 始终为空。有什么想法吗?

【问题讨论】:

  • 你在哪里用 StatusMessage 实例设置你的 DataContext ?

标签: c# .net wpf binding inotifypropertychanged


【解决方案1】:

您的 OnPropertyChanged 字符串必须与属性名称完全匹配,因为它区分大小写。

尝试改变

OnPropertyChanged("StatusMsg");

OnPropertyChanged("statusMsg");

更新:另外 - 刚刚注意到您正在绑定到 StatusMsg(大写“S”);所以控件没有绑定到属性,这是它没有更新的另一个原因!

【讨论】:

  • 我按照 Ian 的建议进行了 2 处更改,PropertyChanged 仍在评估为 NULL。有点奇怪,我知道这应该可行!我编辑了代码以反映更改。
  • @IanR 我不认为它会是 null ,因此,它不会更新他说它甚至没有机会更新的属性,因为它是 null 跨度>
【解决方案2】:

感谢杰罗姆!一旦我设置了 DataContext,它就开始正常工作了!出于测试目的,我在主窗口构造函数中添加了以下内容:

 this.DataContext = testMessage;

【讨论】:

    【解决方案3】:

    当将 PropertyChanged 事件对象观察为 null 时,需要检查几项。

    1. 确保引发事件时作为参数传入的属性名称实际上与您所定位的属性名称匹配。

    2. 确保您只使用包含您要绑定的属性的对象的一个​​实例。

    对于第二项,这可以通过简单地在类构造函数上放置一个断点来完成,该对象包含被绑定的属性。 如果断点被多次触发,那么您就会遇到问题,需要将对象实例的数量解析为运行时通过 XAML 调用的一个实例。

    因此,最好将该类实现为单例模式,这样您就可以确保在运行时只有一个对象实例。

    【讨论】:

    • 什么,辛格尔顿?什么?!我这辈子从来没有读过这么多垃圾。绑定系统将订阅正确的实例事件。如果不是 WPF 将无法正常工作。请参阅任何初学者 MVVM 文章,以获取有关您的错误程度的最佳实践演示。
    • 这是我自己的故障排除经验。我在运行时有多个视图模型实例。因此,此更新对我有用。不过感谢您的意见。
    • 另外,确保所有数据都已加载(即 Loaded 事件)。
    • 我认为 Scott 和 Gusdor 正在谈论不同的员工。 Scott 是在谈论 ViewModel,它确实应该一直都是一样的,而 Gusdor 是在谈论 Model,它肯定可以是任意数量的对象。 Scott 确实启发了我调试类似情况。谢谢。
    【解决方案4】:

    如果您遵循所有说明,验证您的属性名称是否正确,是否正确地为其分配了一个新值,您正在使用单例来保证您的视图模型的一个实例,并且您已在 UI 中成功分配了 DataContext - 确保在可视化树完成后完成强制更新属性的任何操作,即将属性的刷新移动到按钮,而不是说窗口的 Loaded 事件。我这样说是因为我遇到了同样的问题,并且发现当我从 Infragistics NetAdvantage 功能区窗口的 Loaded 事件刷新视图模型数据属性时,我的 PropertyChanged 事件始终为空。

    【讨论】:

    • 这个答案的语法很糟糕,并且没有提供结构化的答案。您提议从视图加载中监视人员,这很复杂,并且可能会使他们更加困惑。如果这确实是您对 null Prop 事件处理程序进行故障排除的方法,您应该提供方法而不是您这样做的示例。
    【解决方案5】:

    我今天遇到这个并浪费了一些时间,最终弄明白了。我希望这可以帮助您和其他人节省一些时间。

    如果您的事件没有订阅者,而您只是将事件声明为:

    public event EventHandler SomeEventHappened;
    

    那么应该是空引用。解决方法是声明如下:

    public event EventHandler SomeEventHappened = delegate { };
    

    这样可以保证你调用as的时候不是空引用

    SomeEventHappened()
    

    我见过的另一种模式是初始化为委托 {} 而是检查 null:

    var eventToRaise = SomeEventHappened;
    if( eventToRaise != null )
    {
        SomeEventHappened()
    }
    

    【讨论】:

    • 设置this.DataContext = testMessage; 使其起作用的原因是,根据我的回答,它有效地建立了您希望触发的事件的订阅,因此它不再为空。
    • 我相信“检查空值”方法现在是首选方法。我确实尝试像在第一个案例中那样初始化事件处理程序,而且,确实,事件不再为空,但 INotifyPropertyChanged 事件没有触发对我正在使用的 List 的更新。解决方法是使用 INotifyCollectionChanged(请参阅:stackoverflow.com/questions/37329991/…,了解我在此问题上的经验)。
    【解决方案6】:

    另一点 - 要让 PropertyChanged 为 null,请确保将对象绑定到 DataContext,然后设置 Path,而不是直接将属性分配给 UI 字段。

    【讨论】:

      【解决方案7】:

      以防万一: 我遇到了类似的问题,但我的错误是实现 INotifyPropertyChanged 的​​类是私有的。公开解决了我的问题。

      【讨论】:

        【解决方案8】:

        当我将现有数据分配给控件的数据绑定属性时,我还看到 PropertyChanged 事件为空:

        <TextBlock Name="CarTireStatus" Text="{Binding TireStatus}" >Bad Text!</TextBlock>
        

        它的工作原理:

        <TextBlock Name="CarTireStatus" Text="{Binding TireStatus}" ></TextBlock>
        

        【讨论】:

          【解决方案9】:

          在我的情况下,它可以工作:

          public partial class MainWindow : Window, INotifyPropertyChanged
          {
              public MainWindow()
              {
                  InitializeComponent();
                  this.DataContext = this;    // this row fixed everything
              }
              ****
              Some code here with properties etc
              ***
          }
          

          【讨论】:

            【解决方案10】:

            我遇到了类似的问题,上述解决方案都没有帮助我。 我需要做的就是使用内置的 c# Propertychanged。 事先我已经实现了 propertyChanged(偶然),但它没有指向任何东西。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-06-15
              • 1970-01-01
              • 1970-01-01
              • 2011-10-13
              • 2015-08-26
              • 2015-07-07
              • 2018-02-03
              相关资源
              最近更新 更多