WPF之HierarchicalDataTemplate


HierarchicalDataTemplate顧名思義,分層數據模板,就是用來定義分層數據樣式的模板,一般多用於MenuItem和TreeViewItem

包含幾個重要屬性

DataType指定模板用於哪種數據類型

ItemsSource指定該類數據的子集,即下一層顯示那些數據

內容 指定數據如何顯示 綁定哪個屬性

MSDN上的一個例子:

1.定義數據集
public class League
    {
        public League(string name)
        {
            _name = name;
            _divisions = new List<Division>();
        }


        string _name;

        public string Name { get { return _name; } }

        List<Division> _divisions;
        public List<Division> Divisions { get { return _divisions; } }

    }
    public class Division
    {
        public Division(string name)
        {
            _name = name;
            _teams = new List<Team>();

        }

        string _name;

        public string Name { get { return _name; } }

        List<Team> _teams;

        public List<Team> Teams { get { return _teams; } }

    }

    public class Team
    {
        public Team(string name)
        {
            _name = name;
        }

        string _name;

        public string Name { get { return _name; } }
    }

    public class ListLeagueList : List<League>
    {
        public ListLeagueList()
        {
            League l;
            Division d;

            Add(l = new League("League A"));
            l.Divisions.Add((d = new Division("Division A")));
            d.Teams.Add(new Team("Team I"));
            d.Teams.Add(new Team("Team II"));
            d.Teams.Add(new Team("Team III"));
            d.Teams.Add(new Team("Team IV"));
            d.Teams.Add(new Team("Team V"));
            l.Divisions.Add((d = new Division("Division B")));
            d.Teams.Add(new Team("Team Blue"));
            d.Teams.Add(new Team("Team Red"));
            d.Teams.Add(new Team("Team Yellow"));
            d.Teams.Add(new Team("Team Green"));
            d.Teams.Add(new Team("Team Orange"));
            l.Divisions.Add((d = new Division("Division C")));
            d.Teams.Add(new Team("Team East"));
            d.Teams.Add(new Team("Team West"));
            d.Teams.Add(new Team("Team North"));
            d.Teams.Add(new Team("Team South"));
            Add(l = new League("League B"));
            l.Divisions.Add((d = new Division("Division A")));
            d.Teams.Add(new Team("Team 1"));
            d.Teams.Add(new Team("Team 2"));
            d.Teams.Add(new Team("Team 3"));
            d.Teams.Add(new Team("Team 4"));
            d.Teams.Add(new Team("Team 5"));
            l.Divisions.Add((d = new Division("Division B")));
            d.Teams.Add(new Team("Team Diamond"));
            d.Teams.Add(new Team("Team Heart"));
            d.Teams.Add(new Team("Team Club"));
            d.Teams.Add(new Team("Team Spade"));
            l.Divisions.Add((d = new Division("Division C")));
            d.Teams.Add(new Team("Team Alpha"));
            d.Teams.Add(new Team("Team Beta"));
            d.Teams.Add(new Team("Team Gamma"));
            d.Teams.Add(new Team("Team Delta"));
            d.Teams.Add(new Team("Team Epsilon"));
        }

        public League this[string name]
        {
            get
            {
                foreach (League l in this)
                    if (l.Name == name)
                        return l;

                return null;
            }
        }


    }
2.窗體
<!--<SnippetHDT>-->
<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="HierarchicalDataTemplate Sample"
  xmlns:src="clr-namespace:SDKSample">
  <DockPanel>
    <DockPanel.Resources>
      <src:ListLeagueList x:Key="MyList"/>

      <HierarchicalDataTemplate DataType    = "{x:Type src:League}"
                                ItemsSource = "{Binding Path=Divisions}">
          
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <HierarchicalDataTemplate DataType    = "{x:Type src:Division}"
                                ItemsSource = "{Binding Path=Teams}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <DataTemplate DataType="{x:Type src:Team}">
        <TextBlock Text="{Binding Path=Name}"/>
      </DataTemplate>
    </DockPanel.Resources>

    <Menu Name="menu1" DockPanel.Dock="Top" Margin="10,10,10,10">
        <MenuItem Header="My Soccer Leagues"
                  ItemsSource="{Binding Source={StaticResource MyList}}" />
    </Menu>

    <TreeView>
      <TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}" Header="My Soccer Leagues" />
    </TreeView>

  </DockPanel>
</Window>

這個例子的數據源是一個分層的List對象,下面一個例子的數據源是一個XML文件,大體相同,不同的地方是需要先實例化一個XmlDataProvider用來獲取XML的內容,綁定的時候用的不是Path,而是XPath屬性,給控件綁定屬性的時候屬性名加@(加@的是屬性Attribute 不加的是子級元素)

1.XML文件
<?xml version="1.0" encoding="utf-8" ?>
<Data xmlns="">
  <Grade Name="初一">
    <Class Name="1班">
      <Group Name="1-1-1組"></Group>
      <Group Name="1-1-2組"></Group>
      <Group Name="1-1-3組"></Group>
    </Class>
    <Class Name="2班">
      <Group Name="1-2-1組"></Group>
      <Group Name="1-2-2組"></Group>
      <Group Name="1-2-3組"></Group>
    </Class>
    <Class Name="3班">
      <Group Name="1-3-1組"></Group>
      <Group Name="1-3-2組"></Group>
      <Group Name="1-3-3組"></Group>
    </Class>
  </Grade>
  <Grade Name="初二">
    <Class Name="21班">
      <Group Name="2-1-1組"></Group>
      <Group Name="2-1-2組"></Group>
      <Group Name="2-1-3組"></Group>
    </Class>
    <Class Name="22班">
      <Group Name="2-2-1組"></Group>
      <Group Name="2-2-2組"></Group>
      <Group Name="2-2-3組"></Group>
    </Class>
    <Class Name="23班">
      <Group Name="2-3-1組"></Group>
      <Group Name="2-3-2組"></Group>
      <Group Name="2-3-3組"></Group>
    </Class>
  </Grade>
  <Grade Name="初三">
    <Class Name="31班">
      <Group Name="3-1-1組"></Group>
      <Group Name="3-1-2組"></Group>
      <Group Name="3-1-3組"></Group>
    </Class>
    <Class Name="32班">
      <Group Name="3-2-1組"></Group>
      <Group Name="3-2-2組"></Group>
      <Group Name="3-2-3組"></Group>
    </Class>
    <Class Name="33班">
      <Group Name="3-3-1組"></Group>
      <Group Name="3-3-2組"></Group>
      <Group Name="3-3-3組"></Group>
    </Class>
  </Grade>
</Data>
2.分層模板
<XmlDataProvider x:Key="Data2" Source="Data.xml" XPath="Data/Grade"/>

        <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath= Class}">
            <TextBlock Text="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">
            <RadioButton Content="{Binding XPath=@Name}" GroupName="gr"/>
        </HierarchicalDataTemplate>
        <HierarchicalDataTemplate DataType="Group" ItemsSource="{Binding XPath=Student}">
            <CheckBox Content="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
3.使用模板
<TreeView Margin="5" ItemsSource="{Binding Source={StaticResource Data2}}"></TreeView>

也試過遞歸方式給TreeView添加節點

View Code
void LoadXmlToTree(XElement root,TreeViewItem item)
        {
            if (root != null)
            {
                foreach (XElement xe in root.Elements())
                {
                    TreeViewItem item2 = new TreeViewItem();
                    item2.Header = xe.Attribute("Name").Value.ToString();
                    item.Items.Add(item2);
                    LoadXmlToTree(xe,item2);
                }
            }
        }

明顯不如模板使用起來方便,但是現在的理解還處於初級階段,只是簡單的套使用方法,知其然,不知其所以然,還有待更進一步的理解,畢竟真正理解透了,原理清楚了,才能更靈活的應用。

 

注:Dictionary類型的需要用values屬性

參考 MSDN 《深入淺出WPF》第11章

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM