如何获取 ItemsControl Items 模板而不是 viewmodel

问题描述 投票:0回答:1

我正在开发一个SpiderGraph控件。这个SpiderGraph继承自ItemsControl,并且可以包含继承自ContentControl的SpiderGraphItems。

[StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(SpiderGraphItem))]
public class SpiderGraph : ItemsControl
{
    public SolidColorBrush Color
    {
        get => (SolidColorBrush)GetValue(ColorProperty);
        set => SetValue(ColorProperty, value);
    }

    public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(SolidColorBrush), typeof(SpiderGraph));

 ...
}
public class SpiderGraphItem : ContentControl
{
    public string Title
    {
        get => (string)GetValue(TitleProperty);
        set => SetValue(TitleProperty, value);
    }

    private static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(SpiderGraphItem));

    public double Value
    {
        get => (double)GetValue(ValueProperty);
        set => SetValue(ValueProperty, value);
    }

    private static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(SpiderGraphItem));

 ...
}

要绘制 SpiderGraph,我需要迭代 Items。 Items 集合包含 SpiderGraphItems。这非常有效,请参见以下内容:(案例 1)

蜘蛛图:

<wpf:SpiderGraph Color="#AA0000FF">
    <wpf:SpiderGraphItem Value="54" Title="Value 1"/>
    <wpf:SpiderGraphItem Value="45" Title="Value 2"/>
    <wpf:SpiderGraphItem Value="85" Title="Value 3"/>
    <wpf:SpiderGraphItem Value="45" Title="Value 4"/>
    <wpf:SpiderGraphItem Value="64" Title="Value 5"/>
</wpf:SpiderGraph>

但是,当我附加 ViewModel 集合时,ItemCollection 项包含由 SpiderGraphItems 代替的 ViewModel,即使我指定 DataTemplate 是 SpiderGraphItem。 (案例2)

<wpf:SpiderGraph Color="#990000FF" ItemsSource="{Binding MyListVM}">
    <wpf:SpiderGraph.ItemTemplate>
        <DataTemplate>
            <wpf:SpiderGraphItem Value="{Binding Value}" Title="{Binding Title}"/>
        </DataTemplate>
    </wpf:SpiderGraph.ItemTemplate>
</wpf:SpiderGraph>

为了绘制多边形,我使用转换器将 ItemCollection 转换为 PointCollection。

<Polygon Fill="{Binding Path=Color, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:SpiderGraph}}}"
Points="{Binding Items, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:SpiderGraph}}, Converter={StaticResource ItemCollectionToSpiderGraphPointCollection}}"/>
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    PointCollection pointCollection = new PointCollection();

    if (value is ItemCollection && targetType == typeof(PointCollection))
    {
        ItemCollection items = (ItemCollection)value;

        if (items.Count > 0)
        {
            double angle = -90;
            foreach (SpiderGraphItem item in items)
            {
                pointCollection.Add(new Point(item.Value * Math.Cos(angle * 0.0175),
                                              item.Value * Math.Sin(angle * 0.0175)));
                angle += 360 / items.Count;
            }
        }
    }
    return pointCollection;
}

(情况 2) 中,ItemCollection 将包含 ViewModel,因此 foreach (SpiderGraphItem item in items) 将导致异常。 我怎样才能在所有情况下获得SpiderGraphItems?

编辑

我尝试使用 ItemContainerGenerator.ContainerFromItem/Index 但它总是返回 null。我还尝试添加 UpdateLayout()。

public SpiderGraph()
{
    Loaded += (o, e) => UpdateGraph();
}

private void UpdateGraph()
{
    base.UpdateLayout();
    foreach (var item in Items)
    {
        //obj is always null
        DependencyObject obj = base.ItemContainerGenerator.ContainerFromItem(item);
        if (obj != null)
        {
            //...
        }
    }
}
c# wpf datatemplate itemcollection
1个回答
0
投票

您尝试过使用 ContentPresenter 吗?

© www.soinside.com 2019 - 2024. All rights reserved.