2013-03-28 4 views
4

У меня есть визуальный контроль в WPF, который использует преимущества свойств зависимостей. Эти свойства поддерживаются полями, которые являются классами, и иногда необходимо уведомить все привязки, что значение свойства изменилось, когда фактически был изменен содержащийся класс.PropertyChanged не подключен

Просто сказал:

  • MyDepProp имеет MyClass типа;
  • Содержимое MyClass изменяется из-за внутренних операций управления;
  • Я хочу сообщить всем, что MyDepProp изменен, чтобы они могли отражать изменения в MyClass.

В MSDN указано, что свойство PropertyChanged привязано к DependencyObject, когда свойство dependency используется впервые. И он работает в Visual Studio 2010. Однако после установки Visual Studio 2012 он прекратил работу: даже несмотря на то, что использовался DP (например, привязка была привязана к нему), PropertyChanged имеет значение null, и я не могу сообщить никому об изменениях.

Я все еще использует Visual Studio 2010 компилятора набор инструменты, поэтому кажется, что это дело битой структуры, которая была обновлена ​​вместе с VS 2012

Использует ли я правильно событие PropertyChanged? Или это ошибка в платформе .NET 4.0, обновленная VS 2012? Кто-нибудь сталкивался с подобной проблемой?


Edit: Кусок кода багги:

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

Сценарий:

  • DataSource является привязан к другому свойству, используя Binding
  • Кто-то называет Handle метод управления (с помощью интерфейса IHandle)
  • Берите проверяет, является ли PropertyChanged не равно нулю, и это, поэтому никакой информации об изменениях в DataSource распространяются.
+1

Можете ли вы показать код, все работает отлично в VS2012 на моем компьютере ... – Peter

+0

Это может быть трудно, на самом деле это часть огромной проекта, и во многих местах этот механизм работает. Вот почему я не могу легко представить код профайла. Если мне удастся это сделать, я отправлю его здесь. Вот почему я спросил, если кто-нибудь столкнулся с этой проблемой тоже :) – Spook

+0

Я использую DP в VS2012 на данный момент без проблем. Убедитесь, что у вас есть один экземпляр datacontext, иначе вы можете обновить неправильный. Также убедитесь, что событие RaisePropertyChanged вызывается с тем же именем, что и свойство. Без кода это были бы первые вещи, которые я бы проверял. – keyboardP

ответ

1

Во-первых, этот код избыточен:

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

Это не рекомендуется писать дополнительный код в обычном инкубаторе собственности, поскольку система WPF DP обращается DPs непосредственно без использования сеттеры или геттеров. Поднять PropertyChanged в OnDataSourceChanged метод.

Во-вторых, ваш контроль наследует DependencyObject, что позволяет добавлять Dependecny Properties.
Существует вероятность, что обновление изменило прежнее поведение, и система DP теперь не подписывается на уведомления через событие ProprtyChanged при привязке к свойству Dependency этого элемента управления, потому что нет необходимости в нем. Система DP имеет свои уведомления.
Это может быть причина, по которой PropertyChanged имеет значение null.

UPDATE

Я думаю, что установка CurrentValue, как вы делаете, может привести к тонким ошибкам. Обычно SetCurrentValue() используется, когда значение должно быть изменено из-за некоторых внутренних причин. Например. TextBox устанавливает значение Text с SetCurrentValue(), когда пользователь вводит текст. Это позволяет сохранять привязки.
Но что произойдет, если вы попытаетесь установить привязки программным путем?

Согласно тому, что вы сказали в комментариях вы можете попробовать:

  • Установить значение NULL, а затем обратно.
  • Реализовать INotifyPropertyChanged для DataSource
  • Вызов DependencyObject.InvalidateProperty()
+0

Если да, то как я могу решить проблему, например. уведомлять об изменениях в свойстве DataSource? И если PropertyChanged не установлен детерминированным способом, как это может быть полезно? У меня сложилось впечатление, что если класс реализует INotifyPropertyChanged, гарантированно будет установлен обработчик PropertyChanged. – Spook

+0

Обратите внимание, что setter вызывает 'SetCurrentValue', а не' SetValue'. Первый не распространяет информацию об изменениях в DP, AFAIK. – Spook

+0

Оба распространяются, но SetCurrent ... не переопределяет источник значений. Ну, зачем вам уведомлять, не было ли реальных изменений в собственности? И если они тогда, система DP сообщит об этом подписчикам. –

Смежные вопросы