我有一个ItemsControl
,用于在画布上绘制两组不同的形状。因此,我有两个ItemsSource
包含Edge对象和Node对象。
我对每种类型都有两个不同的DataTemplates
。但是,我需要为节点设置画布定位,而不是为边缘设置画布定位。互联网上有大量关于如何使用单个ItemsSource
执行此操作的示例,但在我的情况下没有多个示例。
我已经像这样攻击了它,但是这会在输出窗口中引发很多绑定错误(因为只有节点具有Position
属性,而不是边缘,因此这“有效”。另外,我想分别为节点和边缘设置ZIndex
,这是不可能的。有没有人有任何建议?
<ItemsControl>
<ItemsControl.ItemsSource>
<MultiBinding>
<MultiBinding.Converter>
<p:CompositeCollectionConverter/>
</MultiBinding.Converter>
<Binding Path="Graph.Nodes"/>
<Binding Path="Graph.Edges"/>
</MultiBinding>
</ItemsControl.ItemsSource>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type model:Edge}">
<Path
Stroke="Blue"
Data="{Binding Path=EdgeSegments, Converter={StaticResource EdgeSegmentsConverter}}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type model:Node}">
<Ellipse
Width="8"
Height="8"
Stroke="Black"
Fill="Gray"/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left">
<Setter.Value>
<Binding Path="Position.X">
<Binding.Converter>
<p:NodePositionConverter />
</Binding.Converter>
</Binding>
</Setter.Value>
</Setter>
<Setter Property="Canvas.Top">
<Setter.Value>
<Binding Path="Position.Y">
<Binding.Converter>
<p:NodePositionConverter />
</Binding.Converter>
</Binding>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
答案 0 :(得分:1)
为什么不使用ItemContainerStyleSelector?将样式添加到ItemsControl.Resources
:
<Style TargetType="ContentPresenter" x:Key="{x:Type model:Edge}">
<Setter Property="ZIndex">
...
</Setter>
</Style>
<Style TargetType="ContentPresenter" x:Key="{x:Type model:Node}">
<Setter Property="ZIndex">
...
</Setter>
<Setter Property="Canvas.Top">
...
</Setter>
<Setter Property="Canvas.Left">
...
</Setter>
</Style>
请注意x:Key
设置为类型,以便我们可以在样式选择器中轻松查找item.GetType()
:
public override Style SelectStyle(object item, DependencyObject container) {
var containerElement = (FrameworkElement)container;
var style = containerElement.TryFindResource(item.GetType()) as Style;
if (style != null) {
return style;
}
return base.SelectStyle(item, container);
}
答案 1 :(得分:0)
你在做什么有点奇怪..我不知道你是否真的需要这样做...
你不能把你的两个List合并成一个简单的List吗?像这样:
List<AChild> a;
List<BChild> b;
List<Mother> ab = a.Concat(b).Cast<Mother>();
在您的视图中,您可以使用TemplateSelector来帮助您选择适合该项目的DataTemplate。
<ItemsControl ItemTemplateSelector="{StaticResource YourTemplateSelector}" ItemsSource="{Binding ab}"/>
答案 2 :(得分:0)
Rachel在以下StackOverflow主题中给出了答案:https://stackoverflow.com/a/7931448/970589
所以对她赞不绝口。答案的简短摘要: 使用转换器检查调用绑定的类型,并根据该类型返回一个值。