2016-12-05 6 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ラッパーの実装**:*例外的な状況を除いて、ラッパーの実装は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

関連する問題