我实现了自定义面板Shelf
,它根据附加属性Shelf.Exact
排列子项:
class Shelf : Panel
{
public static readonly DependencyProperty ExactProperty = DependencyProperty.RegisterAttached("Exact", typeof(int), typeof(Shelf),
new FrameworkPropertyMetadata(100, new PropertyChangedCallback(OnExactChanged)));
private static void OnExactChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine(d); // This Callback is added only for debug purposes
}
public static int GetExact(UIElement element)
{
return (int)element.GetValue(ExactProperty);
}
public static void SetExact(UIElement element, int value)
{
element.SetValue(ExactProperty, value);
}
protected override Size MeasureOverride(Size availableSize)
{
Size panelSize = new Size(availableSize.Width, 0);
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
panelSize.Height += child.DesiredSize.Height;
}
return panelSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
foreach (UIElement child in InternalChildren)
{
int exact = Shelf.GetExact(child); // Here I always get 100 which is default value for ExactProperty
child.Arrange(new Rect(new Point(0, exact * 1), child.DesiredSize));
}
return finalSize;
}
}
<ItemsControl ItemsSource="{Binding Path=Packs}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:Shelf />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock local:Shelf.Exact="{Binding Path=Number}" Text="{Binding Path=Name}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
就像我在上面的代码评论中提到的那样,我总是得到Shelf.DependencyProperty
的默认值。我无法理解为什么会这样?
第一个想法是绑定是搞乱的。所以我添加PropertyChangedCallback
并检查更改的值是否被触发→调用回调并且d.NewValue
是okey但仍然在ArrangeOverride()
中获得默认值。接下来我完全摆脱了绑定,所以我硬编码local:Shelf.Exact="123"
→我仍然得到默认值。
当我直接使用Shelf
时,它的功能更加完美:
<local:Shelf Grid.Column="1">
<TextBlock local:Shelf.Exact="223">Test</TextBlock>
<TextBlock local:Shelf.Exact="332">Test</TextBlock>
<TextBlock local:Shelf.Exact="443">Test</TextBlock>
</local:Shelf>
答案 0 :(得分:1)
DataTemplate中的TextBlock不是由ItemsPanel测量和排列的元素。
您必须在ItemContainerStyle中的items容器(即ContentPresenter)上设置附加属性:
<ItemsControl ItemsSource="{Binding Packs}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:Shelf/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="local:Shelf.Exact" Value="{Binding Number}"/>
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>