2015-02-03 2 views
1

런타임 중에 IsClosed의 값을 설정하면 OnIsClosedChanged()이 정상적으로 호출됩니다. 그러나 Designer는 속성 값을 설정하지만 OnIsClosedChanged()은 호출하지 않습니다. 분명히 IsClosed
종속성 속성에서 xaml 변경을 수신 할 때의 콜백

public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender)); 

public bool IsClosed { 
    get { 
     return (bool)this.GetValue(IsClosedProperty); 
    } 
    set { 
     if ((bool)this.GetValue(IsClosedProperty) == value) 
      return; 

     this.SetValue(IsClosedProperty, value); 
     OnIsClosedChanged(); 
    } 
} 



private void OnIsClosedChanged() { 
    _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); 
} 

는 디자이너에 의해 수정되지 않습니다 만 IsClosedProperty는 XAML 변화를받습니다.
내 질문은 : 디자이너에서 값을 수정 한 후 IsClosed을 어떻게 실행할 수 있습니까? 또는 최소한 런타임 이외의 변경 사항에 로직을 추가하십시오.

+2

당신이 ValidateValueCallback 함께 놀러하려고 했습니까? DependencyProperty.Register의 오버로드 된 메서드를 사용하십시오. https://msdn.microsoft.com/en-us/library/ms597501(v=vs.110).aspx –

+0

몇 시간 전에 동일한 실수를 범했습니다. 의존성 속성은 무엇인가 깊다. 이 속성은 사용자를 위해 만 노출하지만 WPF는 속성을 사용하지 않습니다 (삭제할 수 있음). 그리고 @AlexK, 주석이 옳다. (답이 될 수도있다.) * 의존성 프로퍼티 * (* 당신의 프로퍼티와 오해하지 말아야 함)가 UI에 의해 변경 될 때 콜백을 사용한다. (디자이너, 런타임에 사용자에 의해 , 등). – Sinatr

답변

5

속성 메타 데이터가 포함 된 PropertyChangedCallback을 등록해야합니다.

XAML 또는 바인딩 또는 다른 원본에서 설정 한 종속성 속성이 CLR 래퍼 (setter 메서드)를 호출하지 않기 때문에 그 때문입니다. 그 이유는 MSDN에 XAML Loading and Dependency Properties 문서에 설명되어 구현 이유로

, 그것을 설정하기보다는 사용하기 위해 부동산 시스템 SetValue는 방법을 종속성 속성으로 속성을 확인하고 액세스 계산 저렴 하는 것입니다 래퍼와 그 세터 인 속성.

...

속성 설정에 대한 XAML 프로세서 동작 의 현재 WPF 구현이 완전히 래퍼를 우회하기 때문에, 당신은하지 는 사용자 정의 의존성에 대한 래퍼의 세트 정의에 추가 논리를 두어야 재산. 이러한 논리를 집합 정의에 넣으면 속성이 이고 코드가 아니라 XAML로 설정된 경우 논리가 실행되지 않습니다.

코드는 다음과 같아야합니다

public static readonly DependencyProperty IsClosedProperty = 
    DependencyProperty.Register(
     "IsClosed", typeof(bool), typeof(GroupBox), 
     new FrameworkPropertyMetadata(false, 
      FrameworkPropertyMetadataOptions.AffectsRender, 
      (o, e) => ((GroupBox)o).OnIsClosedChanged())); 

public bool IsClosed 
{ 
    get { return (bool)GetValue(IsClosedProperty); } 
    set { SetValue(IsClosedProperty, value); } 
} 

private void OnIsClosedChanged() 
{ 
    _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); 
} 
+0

클레멘스가 또 한번! 몇 분 전에 대답을 찾았 어. 하지만 참조는 흥미 롭습니다 ... Thx :) –

1

지금 직접 답변을 찾았습니다. ValidateValueCallback은 정말 가깝습니다! (알렉스 K 지적했다) 그러나 그것은 정적 메서드 및 변경된 인스턴스에 대한 참조를 얻지 않는다. 핵심은 FrameworkPropertyMetadata에서 PropertyChangedCallback을 사용하는 것이며 이는 Property.Register 메서드에 전달되는 인수이기도합니다.
참조 :

public static DependencyProperty IsClosedProperty = DependencyProperty.Register("IsClosed", typeof(bool), typeof(GroupBox), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnIsClosedChangedPCC))); 

     public bool IsClosed { 
      get { 
       return (bool)this.GetValue(IsClosedProperty); 
      } 
      set { 
       this.SetValue(IsClosedProperty, value); 
       OnIsClosedChanged(); 
      } 
     } 



     private static void OnIsClosedChangedPCC(DependencyObject d, DependencyPropertyChangedEventArgs e) { 
      GroupBox current = (GroupBox)d; 
      current.IsClosed = current.IsClosed; 
     } 



     private void OnIsClosedChanged() { 
      _rowDefContent.Height = new GridLength((IsClosed ? 0 : 1), GridUnitType.Star); 
     } 

지금 실행하는 OnIsClosedChanged 트리거 IsClosedValue을-다시 설정 않습니다.
도움 주셔서 감사합니다.

+0

오른쪽. PropertyChangedCallback of course =) –

+1

마지막 단계 : 속성 설정 메소드에서'OnIsClosedChanged()'를 제거하십시오.** PropertyChangedCallback에 ** 속성을 다시 설정하지 마십시오. 그건 말이되지 않습니다. – Clemens