C# 容器如何知道孩子何时调用了InvalidateArrange?
我正在尝试学习在WinRT XAML应用程序中创建自定义面板的基础知识。我已经定义了一个附加的依赖项属性,它按照预期工作,只是我不知道如何获取子元素的属性回调来触发容器的排列或度量 对于孩子来说,让他们的容器知道应该再次调用“排列”和“测量”的正确方法是什么?在我的WPF 4发行的书中,他们使用了FrameworkPropertyMetadataOptions.AffectsParentArrange,但这在WinRT中似乎不可用C# 容器如何知道孩子何时调用了InvalidateArrange?,c#,xaml,windows-runtime,C#,Xaml,Windows Runtime,我正在尝试学习在WinRT XAML应用程序中创建自定义面板的基础知识。我已经定义了一个附加的依赖项属性,它按照预期工作,只是我不知道如何获取子元素的属性回调来触发容器的排列或度量 对于孩子来说,让他们的容器知道应该再次调用“排列”和“测量”的正确方法是什么?在我的WPF 4发行的书中,他们使用了FrameworkPropertyMetadataOptions.AffectsParentArrange,但这在WinRT中似乎不可用 public class SimpleCanvas : Pane
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
}
如果InvalidateArrange单独不起作用,您也可以尝试InvalidateMeasure或UpdateLayout。我参加聚会迟到了,但我走了同一条路,面临着同样的问题。这是我的解决办法 在回调中,对附加属性的子元素调用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();
}
它应该会起作用(对我来说) 我的子控件有这个问题,它依赖于父控件的
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;
}
}
已将回调更改为InvalidateArrange()、InvalidateMeasure()和UpdateLayout(),但容器中未命中ArrangeOverride()和MeasureOverride()中的断点。可能它会检查是否有任何布局属性更改,如果没有,则不会调用它。您可能需要更改一些布局属性,但这可能会破坏现有的绑定。我不敢相信我花了两天的大部分时间试图解决这个问题。。。谢谢!