如何使用不同的元素级别的不同数据模板将XDocument绑定到TreeView?

时间:2014-06-17 06:36:22

标签: c# xml wpf treeview linq-to-xml

我有这个简单的XML:

<ChangeLog>
    <Release Version="1.0.1">
        <Change Name="Feature2" Description="Something changed"/>
        <Change Name="Feature1" Description="Bug fixed"/>
    </Release>
    <Release Version="1.0.0">
        <Change Name="Feature2" Description="Something new added"/>
        <Change Name="Feature1" Description="Something new added"/>
    </Release>
</ChangeLog>

我希望将其显示在TreeView中,如下所示:

enter image description here

我已经查看了herehere以及其他一些相关链接,但我找到的示例使用单HierarchicalDataTemplate来显示项目,而我需要HierarchicalDataTemplate适用于Release元素,DataTemplate适用于Change元素。

例如,对于视图模型,资源中会出现类似的情况(模板树被省略):

<HierarchicalDataTemplate DataType="{x:Type local:Release}" ItemsSource="{Binding Changes}" />
<DataTemplate DataType="{x:Type local:Change}" ItemsSource="{Binding Changes}" />

是否有可能不将XML包装到视图模型中?

1 个答案:

答案 0 :(得分:0)

我已经想通了,怎么做。

解决方案的根目录是DataTemplateSelector,以便为不同的XML元素提供适当的数据模板:

public sealed class ElementsTemplateSelector : DataTemplateSelector
{
    public DataTemplate ReleaseTemplate { get; set; }
    public DataTemplate ChangeTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var element = item as XElement;
        if (element != null)
        {
            switch (element.Name.ToString())
            {
                case "Release":
                    return ReleaseTemplate;
                case "Change":
                    return ChangeTemplate;
            }
        }

        return base.SelectTemplate(item, container);
    }
}

然后XAML将如下所示:

<Grid>
    <Grid.Resources>
        <local:ElementsTemplateSelector x:Key="ElementsTemplateSelectorKey">
            <local:ElementsTemplateSelector.ReleaseTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Elements}">
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Release:"/>
                        <TextBlock Margin="2,0,0,0" Text="{Binding Attribute[Version].Value}"/>
                    </StackPanel>
                </HierarchicalDataTemplate>
            </local:ElementsTemplateSelector.ReleaseTemplate>

            <local:ElementsTemplateSelector.ChangeTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Attribute[Name].Value}"/>
                        <TextBlock Text=":"/>
                        <TextBlock Margin="2,0,0,0" Text="{Binding Attribute[Description].Value}"/>
                    </StackPanel>
                </DataTemplate>
            </local:ElementsTemplateSelector.ChangeTemplate>
        </local:ElementsTemplateSelector>
    </Grid.Resources>

    <TreeView ItemsSource="{Binding Path=Root.Elements}" ItemTemplateSelector="{StaticResource ElementsTemplateSelectorKey}"/>
</Grid>

P.S。此代码假定当前数据上下文为XDocument实例:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = XDocument.Load("file://D:/ChangeLog.xml");
    }
}