来自 CustomPanel 的附加更改 属性 不会刷新面板
Change attached property from CustomPanel doesn't refresh panel
我创建了虚拟自定义面板 ShelfPanel
并附加了 属性 Exact
影响面板排列:
class ShelfPanel : Panel
{
#region Start attached property
public static DependencyProperty ExactProperty = DependencyProperty.RegisterAttached("Exact", typeof(int), typeof(ShelfPanel),
new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.AffectsArrange | // Does this options have auto action?
FrameworkPropertyMetadataOptions.AffectsRender)); // Does this options have auto action?
public static void SetExact(UIElement element, int value)
{
element.SetValue(ExactProperty, value);
}
public static int GetExact(UIElement element)
{
return (int)element.GetValue(ExactProperty);
}
#endregion
protected override Size MeasureOverride(Size availableSize)
{
Size final = new Size();
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
final.Height += child.DesiredSize.Height;
}
return final;
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in InternalChildren)
{
Point position = new Point();
int exact = ShelfPanel.GetExact(child);
// Calculate position based on attached Exact
position.X = exact * 100;
position.Y = exact * 100;
child.Arrange(new Rect(position, child.DesiredSize));
}
return finalSize;
}
}
<local:ShelfPanel>
<local:Box local:ShelfPanel.Exact="0" MouseDown="Box_MouseDown"/>
<local:Box local:ShelfPanel.Exact="1" />
<local:Box local:ShelfPanel.Exact="2" />
</local:ShelfPanel>
public partial class MainWindow : Window // Codebehind for previous xaml
{
public MainWindow()
{
InitializeComponent();
}
private void Box_MouseDown(object sender, MouseButtonEventArgs e)
{
// I certainly sure this code get triggered after click.
ShelfPanel.SetExact(sender as UIElement, 3);
}
}
本作品完美<local:Box>
如期安排。
正如您可以从代码中推断的那样,在点击第一个 <local:Box>
之后,它应该将其位置更改为 3,就在其他 2 之后。但令人惊讶的是没有任何反应。
FrameworkPropertyMetadataOptions.Affects Arrange
或 FrameworkPropertyMetadataOptions.AffectsRender
不会自动重绘面板吗?
为了使这项工作有效,我需要添加 PropertyChangedCallback
并在那里调用 InvalidateVisual()
?
您要在 Box 上设置附加的 属性,但想要 Box 的父元素,即要排列的 ShelfPanel。
因此您应该设置 FrameworkPropertyMetadataOptions.AffectsParentArrange
:
public static readonly DependencyProperty ExactProperty =
DependencyProperty.RegisterAttached("Exact", typeof(int), typeof(ShelfPanel),
new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.AffectsParentArrange));
我创建了虚拟自定义面板 ShelfPanel
并附加了 属性 Exact
影响面板排列:
class ShelfPanel : Panel
{
#region Start attached property
public static DependencyProperty ExactProperty = DependencyProperty.RegisterAttached("Exact", typeof(int), typeof(ShelfPanel),
new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.AffectsArrange | // Does this options have auto action?
FrameworkPropertyMetadataOptions.AffectsRender)); // Does this options have auto action?
public static void SetExact(UIElement element, int value)
{
element.SetValue(ExactProperty, value);
}
public static int GetExact(UIElement element)
{
return (int)element.GetValue(ExactProperty);
}
#endregion
protected override Size MeasureOverride(Size availableSize)
{
Size final = new Size();
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
final.Height += child.DesiredSize.Height;
}
return final;
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in InternalChildren)
{
Point position = new Point();
int exact = ShelfPanel.GetExact(child);
// Calculate position based on attached Exact
position.X = exact * 100;
position.Y = exact * 100;
child.Arrange(new Rect(position, child.DesiredSize));
}
return finalSize;
}
}
<local:ShelfPanel>
<local:Box local:ShelfPanel.Exact="0" MouseDown="Box_MouseDown"/>
<local:Box local:ShelfPanel.Exact="1" />
<local:Box local:ShelfPanel.Exact="2" />
</local:ShelfPanel>
public partial class MainWindow : Window // Codebehind for previous xaml
{
public MainWindow()
{
InitializeComponent();
}
private void Box_MouseDown(object sender, MouseButtonEventArgs e)
{
// I certainly sure this code get triggered after click.
ShelfPanel.SetExact(sender as UIElement, 3);
}
}
本作品完美<local:Box>
如期安排。
正如您可以从代码中推断的那样,在点击第一个 <local:Box>
之后,它应该将其位置更改为 3,就在其他 2 之后。但令人惊讶的是没有任何反应。
FrameworkPropertyMetadataOptions.Affects Arrange
或 FrameworkPropertyMetadataOptions.AffectsRender
不会自动重绘面板吗?
为了使这项工作有效,我需要添加 PropertyChangedCallback
并在那里调用 InvalidateVisual()
?
您要在 Box 上设置附加的 属性,但想要 Box 的父元素,即要排列的 ShelfPanel。
因此您应该设置 FrameworkPropertyMetadataOptions.AffectsParentArrange
:
public static readonly DependencyProperty ExactProperty =
DependencyProperty.RegisterAttached("Exact", typeof(int), typeof(ShelfPanel),
new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.AffectsParentArrange));