2016-12-05 4 views
0

여기에 계속되는 질문은 Trying to setup a custom DependencyObject. Clearly missing something입니다. 원래 질문을 편집하는 것은 실용적이지 않습니다. 변화가 너무 큽니다. 그래서 저는 신선한 질문을 시작하고 있습니다.사용자 지정 DependencyObjects에 대한 바인딩 설정

내 UWP 응용 프로그램에서 사용자 지정 DependencyObjects간에 바인딩을 설정하려고합니다. 관련 코드는 다음과 같습니다. ActualWidthPropertyChanged에 대한 호출이 표시되지만 WidthPropertyChanged에 대한 호출을 트리거하지 않습니다. 내가 뭘 놓치고 있니?

class WindowsElement: DependencyObject 
{ 
    public WindowsElement() 
    { 
    } 
    public double Width 
    { 
     get 
     { 
      return (double)GetValue(WidthProperty); 
     } 
     set 
     { 
      SetValue(WidthProperty, value); 
     } 
    } 

    private static void WidthPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     WindowsElement element = (WindowsElement)o; 
     double width = (double)e.NewValue; 
     CommonDebug.LogLine("WPC", element, o, width); 
     element.Width = width; 
    } 

    private static void ActualWidthPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     WindowsElement element = (WindowsElement)o; 
     double width = (double)e.NewValue; 
     CommonDebug.LogLine("AWPC", o, e, width, element.Width); 
     element.ActualWidth = width; 
    } 
    public static readonly DependencyProperty WidthProperty = DependencyProperty.Register(
     "Width", 
     typeof(double), 
     typeof(WindowsElement), 
     new PropertyMetadata((double)0, WidthPropertyChanged)); 

     public double ActualWidth { 
     get 
      { 
      return (double)GetValue(ActualWidthProperty); 
      } 
     set 
      { 
       SetValue(ActualWidthProperty, value); 
      } 
     } 


    public static readonly DependencyProperty ActualWidthProperty = 
     DependencyProperty.Register(
     "ActualWidth", 
     typeof(double), 
     typeof(WindowsElement), 
     new PropertyMetadata((double)0, ActualWidthPropertyChanged)); 


    public static void MessWithBindings() 
    { 
     WindowsElement we1 = new WindowsElement(); 
     WindowsElement we2 = new WindowsElement(); 
     var b = new Binding 
      { 
      Source = we2, 
      Path = new PropertyPath("ActualWidth") 
      }; 

     BindingOperations.SetBinding(we1, WindowsElement.WidthProperty, b); 
     we2.ActualWidth = 13; 
     CommonDebug.LogLine(we1, we1.Width, we1.ActualWidth, we2, we2.Width, we2.ActualWidth); 
    } 
} 

답변

1

나는 ActualWidthPropertyChanged에 전화를보고하고 있지만 WidthPropertyChanged에 대한 호출을 트리거하지 않습니다. 내가 뭘 놓치고 있니?

소스를 수정할 수 있도록 소스 개체에 INotifyPropertyChanged 인터페이스를 구현해야합니다.

다음 코드를 참조하십시오

class WindowsElement : DependencyObject, INotifyPropertyChanged 
{ 
    public WindowsElement() 
    { 
    } 

    public double Width 
    { 
     get 
     { 
      return (double)GetValue(WidthProperty); 
     } 
     set 
     { 
      SetValue(WidthProperty, value); 
     } 
    } 

    private static void WidthPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     WindowsElement element = (WindowsElement)o; 
     double width = (double)e.NewValue; 
     CommonDebug.LogLine("WPC", element, o, width); 
     //element.Width = width; 
     element.RaisedPropertyChanged("Width"); 
    } 

    private static void ActualWidthPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     WindowsElement element = (WindowsElement)o; 
     double width = (double)e.NewValue; 
     CommonDebug.LogLine("AWPC", o, e, width, element.Width); 
     //element.ActualWidth = width; 
     element.RaisedPropertyChanged("ActualWidth"); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void RaisedPropertyChanged(string PropertyName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName)); 
    } 

    public static readonly DependencyProperty WidthProperty = DependencyProperty.Register(
     "Width", 
     typeof(double), 
     typeof(WindowsElement), 
     new PropertyMetadata((double)0, WidthPropertyChanged)); 

    public double ActualWidth 
    { 
     get 
     { 
      return (double)GetValue(ActualWidthProperty); 
     } 
     set 
     { 
      SetValue(ActualWidthProperty, value); 
     } 
    } 

    public static readonly DependencyProperty ActualWidthProperty = DependencyProperty.Register(
     "ActualWidth", 
     typeof(double), 
     typeof(WindowsElement), 
     new PropertyMetadata((double)0, ActualWidthPropertyChanged)); 

    public static void MessWithBindings() 
    { 
     WindowsElement we1 = new WindowsElement(); 
     WindowsElement we2 = new WindowsElement(); 
     var b = new Binding 
     { 
      Source = we2, 
      Path = new PropertyPath("ActualWidth") 
     }; 

     BindingOperations.SetBinding(we1, WindowsElement.WidthProperty, b); 
     we2.ActualWidth = 13; 
     CommonDebug.LogLine(we1, we1.Width, we1.ActualWidth, we2, we2.Width, we2.ActualWidth); 
    } 
} 
+0

참조 [** 사용자 정의 종속성 속성 **] (https://msdn.microsoft.com/en를 -us/windows/uwp/xaml-platform/custom-dependency-properties), 섹션 ** 래퍼 구현 ** : * 예외적 인 상황을 제외하고 래퍼 구현은 GetValue 및 SetValue 작업 만 수행해야합니다. 그렇지 않으면 XAML을 통해 속성을 설정할 때와 코드를 통해 속성을 설정할 때 각각 다른 동작을 보입니다. 효율성을 위해 XAML 파서는 종속성 속성을 설정할 때 래퍼를 무시합니다. SetValue *를 통해 백킹 스토어와 대화한다. – Clemens

+0

PropertyChanged 이벤트를 발생 시키려면 (필요한 경우) PropertyChangedCallback에서 수행해야합니다. – Clemens

+1

@Clemens 네 말이 맞아. 래퍼에서 PropertyChanged를 호출하는 것은 좋은 습관이 아닙니다. 나는 나의 답장을 갱신했다. 이 문제는 특별한 경우 여야합니다. INotifyPropertyChanged 인터페이스를 구현해야합니다. –

0

UWP에서 단방향 (이것은 WPF에서와 같이) 자동으로 대상의 속성을 업데이트하지 않는 다른 하나 개의 종속성 속성에서 바인딩 왜 확실하지.

그러나, 당신은 단순히 바인딩의 방향을 되돌릴과 양방향 만들 수 :

var b = new Binding 
{ 
    Source = we1, 
    Path = new PropertyPath("Width"), 
    Mode = BindingMode.TwoWay 
}; 

BindingOperations.SetBinding(we2, WindowsElement.ActualWidthProperty, b); 
we2.ActualWidth = 13; 
+0

WidthPropertyChanged에 대한 콜백이 없습니다. . . –

+0

그것은 나를 위해 작동합니다. 그리고 PropertyChangedCallbacks에서'element.Width = width;'와'element.ActualWidth = width;'를 호출해서는 안됩니다. 이 속성은 이미 변경되었으므로 다시 설정할 필요가 없습니다. – Clemens