2016-12-05 47 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