我正在开发一个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)
{
//...
}
}
}
您尝试过使用 ContentPresenter 吗?