title: How does a container know when a child has called InvalidateArrange?
body: <p>I'm trying to learn the basics of creating a custom panel in a WinRT XAML app. I have defined an attached dependency property and it's working as expected except i can't figure out how to get the property's callback for a child element to trigger the arrange or measure of the container.</p>
  
  <p>What's the proper way to for a child to let it's container know that arrange and measure should be called again? In my WPF 4 unleashed book they use the FrameworkPropertyMetadataOptions.AffectsParentArrange but that doesn't seem to be available in WinRT.</p>
  
  <pre><code>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
  }
  </code></pre>