PropertyChanged没有附加

时间:2013-03-28 10:06:08

标签: c# .net wpf events dependency-properties

我在WPF中有一个可视化控件,它利用了依赖属性。这些属性由字段支持,这些字段是类,有时需要在实际修改包含的类时通知所有绑定,更改属性值。

简单地说:

  • MyDepProp属于MyClass;
  • 由于控件的内部操作,MyClass的内容发生了变化;
  • 我想告诉大家,MyDepProp发生了变化,以便他们能够反映MyClass中的变化。

MSDN说,当首次使用依赖属性时,PropertyChanged附加到DependencyObject。它在Visual Studio 2010中有效。但是,在安装Visual Studio 2012后,它停止工作:即使使用了DP(例如绑定附加到它),PropertyChanged也为null,我无法通知任何人更改。

我仍然使用Visual Studio 2010编译工具包,所以看起来,这是一个破坏框架的问题,它与VS 2012一起更新。

我是否正确使用PropertyChanged事件?或者它是VS 2012更新的.NET 4.0框架中的错误?有没有人遇到类似的问题?


编辑:一段错误的代码:

public partial class MyImageControl : INotifyPropertyChanged,
    IHandle<ImageRefresh>
{
    // ***************************
    // *** Dependency property ***
    // ***************************

    private void OnDataSourceChanged()
    {
        // ...
    }

    private static void DataSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is MyImageControl)
            ((MyImageControl)d).OnDataSourceChanged();
    }

    public static readonly DependencyProperty DataSourceProperty = DependencyProperty.Register("DataSource",
        typeof(IDataSource),
        typeof(MyImageControl),
        new PropertyMetadata(null, DataSourceChanged));

    public IDataSource DataSource
    {
        get
        {
            return (IDataSource)GetValue(DataSourceProperty);
        }

        set
        {
            SetCurrentValue(DataSourceProperty, value);
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("DataSource"));
        }
    }

    // ***********************************
    // *** INotifyPropertyChanged impl ***
    // ***********************************

    public event PropertyChangedEventHandler PropertyChanged;

    // *************************************
    // *** Method, which exposes the bug ***
    // *************************************

    public void Handle(ImageRefresh message)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("BackgroundKind"));
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("DataSource"));
    }
}

作为参考,IHandle接口:

public interface IBaseHandle { }

public interface IHandle<TMessage> : IBaseHandle
{
    void Handle(TMessage message);
}

情景:

  • 使用Binding
  • 将DataSource 绑定到另一个属性
  • 有人调用控件的Handle方法(使用IHandle接口)
  • 处理检查,PropertyChanged是否为空,因此不会传播有关DataSource更改的信息。

1 个答案:

答案 0 :(得分:1)

首先,这段代码是多余的:

            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("DataSource"));

不建议在通常的属性设置器中编写任何其他代码,因为WPF DP系统直接访问DP而不使用setter或getter。 在PropertyChanged方法中提升OnDataSourceChanged

其次,您的控件继承了DependencyObject允许您添加Dependecny属性的内容 有可能更新改变了以前的行为,并且当绑定到控件的依赖属性时,DP系统现在不会通过ProprtyChanged事件订阅通知,因为不需要它。 DP系统有通知。
这可能是PropertyChanged为空的原因。

<强>更新

我认为像你一样设置CurrentValue会导致细微的错误。通常由于某些内部原因而应更改值时使用SetCurrentValue()。例如。当用户键入文本时,TextBox会将Text属性值设置为SetCurrentValue()。这样可以保存绑定 但是,如果您尝试以编程方式设置绑定会发生什么?

根据您在评论中所说的内容,您可以尝试:

  • 将值设置为null然后返回。
  • 为DataSource实施INotifyPropertyChanged
  • 致电DependencyObject.InvalidateProperty()