2013-03-28 4 views
4

종속성 속성을 활용하는 WPF에서 시각적 컨트롤이 있습니다. 이러한 속성은 클래스 인 필드에 의해 뒷받침되며 실제로 포함 된 클래스가 수정되었을 때 속성의 값이 변경된 경우 모든 바인딩에 알릴 필요가있는 경우가 있습니다.PropertyChanged가 첨부되지 않았습니다.

는 간단히 말했다 :

  • MyDepProp 유형의 MyClass에이다;
  • MyClass의 내용은 컨트롤의 내부 작업으로 인해 변경됩니다.
  • MyDepProp이 변경되어 MyClass의 변경 사항을 반영 할 수 있도록 모든 사람에게 알려 드리고 싶습니다.

MSDN에 따르면 종속성 속성을 처음 사용할 때 PropertyChanged가 DependencyObject에 연결됩니다. 그러나 Visual Studio 2010을 설치 한 후에는 Visual Studio 2012를 설치 한 후 작동이 중지되었습니다. DP를 사용 했는데도 (예 : 바인딩이 첨부되어 있음) PropertyChanged는 null이며 아무에게도 변경 사실을 알릴 수 없습니다. 것 같다 있도록

나는 여전히

내가 올바르게하여 PropertyChanged 이벤트를 사용하십니까 VS 2012와 함께 업데이트 된 깨진 프레임 워크의 문제 것을, 비주얼 스튜디오 2010 컴파일러 툴킷을 사용? 아니면 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
  • 사람을 사용하여 다른 속성 바인딩, 데이터 소스의 변화를 그래서 정보를하여 PropertyChanged가 널인지의 여부,
  • 핸들 검사합니다 (IHandle 인터페이스를 사용하여) 제어 Handle 메소드를 호출하지 않고 그 것이다 전파됩니다.
+1

당신이 몇 가지 코드를 보여줄 수 전화

  • 데이터 소스
    에 대한 INotifyPropertyChanged을 구현, 모든이가 힘들 수도 ... 내 PC에서 VS2012에서 – Peter

  • +0

    을 잘 작동, 그것은 실제로 거대한의 일부 프로젝트와 많은 곳에서이 메커니즘이 작동합니다. 이것이 내가 개념 실현 코드를 쉽게 제공 할 수없는 이유입니다. 그렇게 할 수 있다면 여기에 게시 할 것입니다. 그래서 내가이 질문에 너무 어려움을 겪었다 고 묻는 이유는 무엇입니까? – Spook

    +0

    현재 문제없이 VS2012에서 DP를 사용하고 있습니다. datacontext의 한 인스턴스가 있는지 확인하십시오. 그렇지 않으면 잘못된 인스턴스를 업데이트 할 수 있습니다. RaisePropertyChanged 이벤트가 속성과 동일한 이름으로 호출되는지 확인하십시오. 코드가 없다면 그것들이 제가 확인한 첫 번째 것이 될 것입니다. – keyboardP

    답변

    1

    첫째,이 코드는 중복 : WPF DP 시스템은 세터 또는 게터를 사용하지 않고 직접 DP들에 접근하기 때문에 일반적인 속성 setter에 추가 코드를 작성하지 않는 것이 좋습니다

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

    . PropertyChangedOnDataSourceChanged 방법으로 올리십시오.

    둘째로, 컨트롤에 DependencyObject이 상속되어 Dependecny Properties를 추가 할 수 있습니다.
    업데이트가 이전 동작을 변경했을 가능성이 있으며 DP 시스템은 필요 없기 때문에 컨트롤의 종속성 속성에 바인딩 할 때 ProprtyChanged 이벤트를 통해 알림을 구독하지 않습니다. DP 시스템에는 통지가 있습니다.
    그 이유는 PropertyChanged이 null 일 수 있습니다.

    UPDATE는

    생각 당신이 미묘한 버그로 이어질 수처럼 CurrentValue에 설정. 일반적으로 SetCurrentValue()은 내부적 인 이유로 인해 값을 변경해야하는 경우에 사용됩니다. 예 : TextBox은 사용자가 텍스트를 입력 할 때 Text 속성 값을 SetCurrentValue()으로 설정합니다. 이렇게하면 바인딩을 저장할 수 있습니다.
    그러나 바인딩을 프로그래밍 방식으로 설정하려고하면 어떻게됩니까? 그때 null로

    • 설정 값과 : 당신은 당신이 시도 할 수 코멘트에 말한에 따르면

      .

    • DependencyObject.InvalidateProperty()
    +0

    그렇다면 어떻게 문제를 해결할 수 있습니까? DataSource 속성 내의 변경 사항에 대해 알리시겠습니까? 그리고 PropertyChanged가 결정론적인 방식으로 설정되지 않은 경우 어떻게 유용 할 수 있습니까? 클래스에 INotifyPropertyChanged를 구현하면 PropertyChanged 핸들러가 설정된다는 보장이 있습니다. – Spook

    +0

    setter는 SetValue가 아니라'SetCurrentValue'를 호출합니다. 첫 번째는 AFAIK의 변경 사항에 대한 정보를 전파하지 않습니다. – Spook

    +0

    둘 다 전파되지만 SetCurrent ...는 값 소스를 대체하지 않습니다. 글쎄, 재산의 실제 변화가 없다면 왜 신고해야합니까? 그리고 그들이 그때이면 DP 체계는 구내 구독자에게 통지 할 것이다. –

    관련 문제