【问题标题】:Different DataTemplate depending on the enumeration value of a property根据属性的枚举值不同的DataTemplate
【发布时间】:2012-07-13 07:17:16
【问题描述】:

我想要类似于 here 所要求的内容 - 但是,我需要模板依赖于属性的值,即枚举。

这个类看起来和这个很相似:

class ResultBlock
{
    public string Name { get; set; }
    public BlockType Type { get; set; }
    public IList<ResultBlock> ChildBlocks { get; private set; }
}

BlockType 具有三个不同的值,BLOCK, FILE, FOLDER - 现在,我想创建一个数据模板以不同的方式呈现,具体取决于 ResultBlock.Type 在当前对象中的值。

我尝试使用DataType= 执行此操作,但显然没有成功。我确信有一些方法可以仅在 XAML 中很容易地做到这一点。

<TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type docom:ResultBlock}" ItemsSource="{Binding ChildBlocks}">
        <StackPanel Orientation="Horizontal">
            <StackPanel.Resources>
                <DataTemplate DataType="{x:Type docom:BlockType.BLOCK}">
                    <TextBlock Text="BLOCK:{Binding Name}" />
                </DataTemplate>
            </StackPanel.Resources>
        </StackPanel>
    </HierarchicalDataTemplate>
</TreeView.Resources>

【问题讨论】:

  • 如果只有BLOCK: 前缀发生变化,您可以简单地将TextBlock 绑定到BlockType 属性。

标签: c# wpf xaml data-binding


【解决方案1】:

您可以在属性上触发,例如:

<HierarchicalDataTemplate DataType="{x:Type docom:ResultBlock}"
                          ItemsSource="{Binding ChildBlocks}">
    <ContentControl Content="{Binding}">
        <ContentControl.Style>
            <Style TargetType="ContentControl">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding BlockType}" Value="BLOCK"> 
                        <Setter Property="ContentTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                     <!-- Data template for BLOCK blocks -->
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <!-- More triggers -->
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</HierarchicalDataTemplate>

是的,它很冗长。 (您可以将不同类型的模板定义为键控资源,然后在Setters 中引用它们)

【讨论】:

  • 对我来说根本不起作用。引发了以下 XamlParseException:尝试添加到不是集合或具有 TypeConverter 的 Setter。
  • @HankSchultz:你显然做错了什么,听起来很像语法错误。也许像缺少&lt;Setter.Value&gt; 标签之类的东西?没有确切的代码很难说。
  • 可能,但我没有发现任何明显的错误。我最终使用样式触发器根据所需的属性值设置 Visibility 属性,这具有相同的可见效果。
【解决方案2】:
<Window.Resources>
    <local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
</Window.Resources>
<Grid>
    <ListBox Width="400" Margin="10"
     ItemsSource="{Binding Source={StaticResource myTodoList}}"
     ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
     HorizontalContentAlignment="Stretch"/>
</Grid>
public class TaskListDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate
        SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement element = container as FrameworkElement;

        if (element != null && item != null && item is Task)
        {
            Task taskitem = item as Task;

            if (taskitem.Priority == 1)
                return
                    element.FindResource("importantTaskTemplate") as DataTemplate;
            else
                return
                    element.FindResource("myTaskTemplate") as DataTemplate;
        }

        return null;
    }
}

这是为 ListBox 实现的,但对于 DataGrid/TreeView 的想法可以相同。我希望这会有所帮助。

【讨论】:

  • 您能否展示完整的示例,说明定义 TaskTemplate 和 myTaskTemplate 的重要性?
【解决方案3】:

一种方法是使用 TemplateSelector 并在选择器中根据您的 BlockType 执行您想要的操作。

或者您创建包装视图模型,例如:

 public class ResultBlockBlock{}
 public class ResultBlockFile{}
 public class ResultBlockFolder{}

那么你可以走DataTemplate DataType的方式

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 2010-12-20
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多