【问题标题】:Set style for specific item type in ItemsControl在 ItemsControl 中为特定项目类型设置样式
【发布时间】:2014-04-15 11:53:48
【问题描述】:

我有一个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>

【问题讨论】:

    标签: c# wpf


    【解决方案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);
        }
    

    【讨论】:

    • 我又重新审视了这个问题,并尝试了你的解决方案。它工作得很好,比我的解决方案更优雅,因此接受了你的回答。谢谢!
    【解决方案2】:

    你在做什么有点奇怪..我不知道你是否真的需要这样做......

    您不能将两个 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}"/>
    

    【讨论】:

    • 我不想合并这两个集合,ItemsSource 绑定工作得很好,所以这不是我的问题。另外,据我所知,TemplateSelector 与DataTemplate 一起使用,但我需要在Canvas 上设置属性,这就是为什么我需要在ItemContainerStyle 中设置单独的样式。
    【解决方案3】:

    Rachel 在以下 StackOverflow 线程中给出了答案:https://stackoverflow.com/a/7931448/970589

    非常感谢她。答案的简短摘要: 使用转换器检查调用绑定的类型,并根据该类型返回一个值。

    【讨论】:

      猜你喜欢
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      相关资源
      最近更新 更多