2012-10-19 27 views
6

私は、WinRT XAMLアプリケーションでカスタムパネルを作成する基本を学びたいと考えています。私は添付された依存関係プロパティを定義していますが、コンテナの配置または寸法をトリガーする子要素のプロパティのコールバックを取得する方法を見つけることができない場合を除いて、期待どおり動作しています。コンテナは、子がInvalidateArrangeを呼び出したときをどのように知っていますか?

子供がアレンジと測定を再度呼び出す必要があることをコンテナに知らせる適切な方法は何ですか? WPF 4の解説書では、FrameworkPropertyMetadataOptions.AffectsParentArrangeを使用していますが、WinRTでは使用できないようです。

public class SimpleCanvas : Panel 
{ 
    #region Variables 
    #region Left Property 
    public static double GetLeft(UIElement element) 
    { 
     if (element == null) 
     { 
      throw new ArgumentNullException("element"); 
     } 

     object value = element.GetValue(LeftProperty); 
     Type valueType = value.GetType(); 
     return Convert.ToDouble(value); 
    } 

    public static void SetLeft(UIElement element, double value) 
    { 
     if (element == null) 
     { 
      throw new ArgumentNullException("element"); 
     } 

     element.SetValue(LeftProperty, value); 
    } 

    public static readonly DependencyProperty LeftProperty = 
     DependencyProperty.RegisterAttached("Left", typeof(double), typeof(SimpleCanvas), 
     new PropertyMetadata(0, OnLeftPropertyChanged)); 

    public static void OnLeftPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
    { 
     UIElement element = (UIElement)source; 
     // This doesn't cause ArrangeOverride below to be called 
     element.InvalidateArrange(); 
    } 
    #endregion 

    #region Top Property 
    public static double GetTop(UIElement element) 
    { 
     if (element == null) 
     { 
      throw new ArgumentNullException("element"); 
     } 

     object value = element.GetValue(TopProperty); 
     return (value == null) ? 0 : (double)value; 
    } 

    public static void SetTop(UIElement element, double value) 
    { 
     if (element == null) 
     { 
      throw new ArgumentNullException("element"); 
     } 

     element.SetValue(TopProperty, value); 
    } 

    public static readonly DependencyProperty TopProperty = 
     DependencyProperty.RegisterAttached("Top", typeof(double), typeof(SimpleCanvas), 
     new PropertyMetadata(0, OnTopPropertyChanged)); 

    public static void OnTopPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
    { 
     UIElement element = (UIElement)source; 
     // This doesn't cause ArrangeOverride below to be called 
     element.InvalidateArrange(); 
    } 
    #endregion 
    #endregion 

    public SimpleCanvas() 
    { 

    } 

    #region Methods 
    protected override Size MeasureOverride(Size availableSize) 
    { 
     foreach (UIElement child in this.Children) 
     { 
      child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); 
     } 

     return new Size(0, 0); 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     foreach (UIElement child in this.Children) 
     { 
      double x = 0; 
      double y = 0; 

      double left = GetLeft(child); 
      double top = GetTop(child); 

      if (!double.IsNaN(left)) 
      { 
       x = left; 
      } 
      if (!double.IsNaN(top)) 
      { 
       y = top; 
      } 

      child.Arrange(new Rect(new Point(x, y), child.DesiredSize)); 
     } 

     return finalSize; 
    } 
    #endregion 
} 

答えて

0

InvalidateArrangeだけでは機能しない場合は、InvalidateMeasureまたはUpdateLayoutを試すこともできます。

+1

InvalidateArrangeに変更されたコールバック()、InvalidateMeasureを()、およびUpdateLayout()どちらもArrangeOverrideにブレークポイント()もMeasureOverrideは、()でヒットしていますコンテナ – user263619

+0

レイアウトプロパティが変更されたかどうかをチェックし、レイアウトプロパティがない場合はそれを呼び出します。レイアウトプロパティの一部を変更する必要がありますが、既存のバインディングが破損する可能性があります。 –

3

私はパーティーに遅れましたが、私は同じ方向に行き、同じ問題に直面しました。ここに私の解決策があります。あなたのコールバックで

あなたはあなたにあなた添付プロパティを子要素にInvalidateArrangeを呼び出す:

public static void OnTopPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    UIElement element = (UIElement)source; 
    // This doesn't cause ArrangeOverride below to be called 
    element.InvalidateArrange(); 
} 

しかし、あなたは本当にそうあなたのコードを変更することで、パネルを無効にする必要があります

public static void OnTopPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    UIElement panel= VisualTreeHelper.GetParent(source) as UIElement; 
    if(panel != null)  
     panel.InvalidateArrange(); 
} 

そして、それを(私のために)うまくいくはずです。

+0

これは答えとしてマークする必要があります。 – Yawar

+0

私はちょうどこれを理解しようと2日間のより良い部分を過ごしたと信じることができません...ありがとう! – Gaet

0

親コントロールのFontSizeに依存する子コントロールでこの問題が発生しました。私は両親のスタックを旅し、すべて無効化することにより、問題を解決:

static MyControl() 
    { 
     // replace base implementation of the dependent property 
     FontSizeProperty.OverrideMetadata(typeof(Scalar), 
      new FrameworkPropertyMetadata(SystemFonts.MessageFontSize, FrameworkPropertyMetadataOptions.Inherits, OnMeasureInvalidated)); 
    } 

    private static void OnMeasureInvalidated(DependencyObject sender, DependencyPropertyChangedEventArgs args) 
    { 
     // recurse over parent stack 
     while (true) 
     { 
      var parent = VisualTreeHelper.GetParent(sender) as UIElement; 
      if (parent == null) return; // break on root element 
      parent.InvalidateMeasure(); 
      sender = parent; 
     } 
    }