自定义面板实现期间ItemsControl中附加属性的值

时间:2018-01-11 09:49:10

标签: wpf wpf-controls

我实现了自定义面板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>

1 个答案:

答案 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>
相关问题