前言 在項(xiàng)目開發(fā)中,常常需要以樹的形式來組織數(shù)據(jù)的層次關(guān)系,最常用的控件莫過于TreeView了,本文就是對(duì)如何在TreeView中實(shí)現(xiàn)分層數(shù)據(jù)顯示進(jìn)行介紹。 固定內(nèi)容的樹 當(dāng)TreeView中的內(nèi)容為固定值的時(shí)候,我們可以直接使用xaml對(duì)其內(nèi)容進(jìn)行設(shè)置,而不必使用代碼綁定,這樣做的好處是設(shè)置簡(jiǎn)單且系統(tǒng)負(fù)擔(dān)較輕。 示例代碼如下
前言
在項(xiàng)目開發(fā)中,常常需要以樹的形式來組織數(shù)據(jù)的層次關(guān)系,最常用的控件莫過于TreeView了,本文就是對(duì)如何在TreeView中實(shí)現(xiàn)分層數(shù)據(jù)顯示進(jìn)行介紹。
固定內(nèi)容的樹
當(dāng)TreeView中的內(nèi)容為固定值的時(shí)候,我們可以直接使用xaml對(duì)其內(nèi)容進(jìn)行設(shè)置,而不必使用代碼綁定,這樣做的好處是設(shè)置簡(jiǎn)單且系統(tǒng)負(fù)擔(dān)較輕。
示例代碼如下:
<sdk:TreeView Name="tviSample" VerticalAlignment="Top">
<sdk:TreeViewItem Header="茶" >
<sdk:TreeViewItem Header="鐵觀音">
<sdk:TreeViewItem Header="福建"></sdk:TreeViewItem>
<sdk:TreeViewItem Header="云南"></sdk:TreeViewItem>
</sdk:TreeViewItem>
<sdk:TreeViewItem Header="龍井"></sdk:TreeViewItem>
<sdk:TreeViewItem Header="茉莉花"></sdk:TreeViewItem>
</sdk:TreeViewItem>
<sdk:TreeViewItem Header="書">
<sdk:TreeViewItem Header="計(jì)算機(jī)類">
<sdk:TreeViewItem Header="銀光志"></sdk:TreeViewItem>
</sdk:TreeViewItem>
<sdk:TreeViewItem Header="歷史小說類">
<sdk:TreeViewItem Header="明朝那些事兒"></sdk:TreeViewItem>
<sdk:TreeViewItem Header="歷史是個(gè)什么玩意兒"></sdk:TreeViewItem>
</sdk:TreeViewItem>
</sdk:TreeViewItem>
</sdk:TreeView>
在Visual Studio IDE中通過設(shè)置TreeView的Items屬性,可以很快的為樹添加子成員,也可為子成員(ListViewItem)繼續(xù)添加子成員。
動(dòng)態(tài)綁定內(nèi)容的樹
但是絕大多數(shù)的情況下,樹的內(nèi)容是需要通過代碼動(dòng)態(tài)生成的,對(duì)于動(dòng)態(tài)生成的樹,可以使用下面的實(shí)例代碼來實(shí)現(xiàn)和上述xaml代碼一樣的效果(雖然這樣做意義不大…):
<sdk:TreeView Name="tviSample" VerticalAlignment="Top">
</sdk:TreeView>
public MainPage()
{
InitializeComponent();
TreeViewItem tviItem = new TreeViewItem() { Header = "茶" };
TreeViewItem tviSubItem=new TreeViewItem(){ Header="鐵觀音"};
tviSubItem.Items.Add(new TreeViewItem() { Header = "福建" });
tviSubItem.Items.Add(new TreeViewItem() { Header = "云南" });
tviItem.Items.Add(tviSubItem);
tviSubItem = new TreeViewItem() { Header = "龍井" };
tviItem.Items.Add(tviSubItem);
tviSubItem = new TreeViewItem() { Header = "茉莉花" };
tviItem.Items.Add(tviSubItem);
tviSample.Items.Add(tviItem);
tviItem = new TreeViewItem() { Header = "書" };
tviSubItem = new TreeViewItem() { Header = "計(jì)算機(jī)" };
tviSubItem.Items.Add(new TreeViewItem() { Header = "銀光志" });
tviItem.Items.Add(tviSubItem);
tviSubItem = new TreeViewItem() { Header = "歷史小說" };
tviSubItem.Items.Add(new TreeViewItem() { Header = "明朝那些事兒" });
tviItem.Items.Add(tviSubItem);
tviSample.Items.Add(tviItem);
}
上面的例子雖然是使用代碼為樹添加子節(jié)點(diǎn)或葉子節(jié)點(diǎn),但是在實(shí)際的項(xiàng)目開發(fā)中,我們更多的是使用一個(gè)自定義的數(shù)據(jù)源,比如說ObservableCollection(使用這個(gè)類需要引入 System.Collections.ObjectModel命名空間)的一個(gè)對(duì)象來綁定到樹的數(shù)據(jù)源上,再將對(duì)象的某系字段綁定到樹的模板上。這個(gè)時(shí)候,就該 HierarchicalDataTemplate 閃亮登場(chǎng)了,HierarchicalDataTemplate就是專門用來配合TreeView實(shí)現(xiàn)數(shù)據(jù)綁定效果的,如以下代碼所示:
<sdk:TreeView Name="tviSample" ItemsSource="{Binding}"VerticalAlignment="Top">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=SubItems}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=GoodsName}"></TextBlock>
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
</sdk:TreeView>
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection currentGoods = new ObservableCollection();
currentGoods.Add(new Goods() { GoodsName = "書1", GoodsId = 1 });
currentGoods.Add(new Goods() { GoodsName = "書2", GoodsId = 2 });
tviSample.DataContext = currentGoods;
}
}
public class Goods
{
public string GoodsName { get; set; }
public int GoodsId { get; set; }
public Goods() { }
public Goods(string GoodsName, int GoodsId)
{
this.GoodsId = GoodsId;
this.GoodsName = GoodsName;
}
}
以上實(shí)例實(shí)現(xiàn)了一層的綁定,想實(shí)現(xiàn)兩層綁定該如何處理?請(qǐng)看下面示例代碼:
<Grid x:Name="LayoutRoot" Loaded="LayoutRoot_Loaded">
<Grid.Resources>
<sdk:HierarchicalDataTemplate x:Key="ChildTemplate" >
<TextBlock Text="{Binding Path=GoodsName}"></TextBlock>
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="RootTemplate" ItemsSource="{Binding SubItems}" temTemplate="{StaticResource ChildTemplate}" >
<TextBlock Text="{Binding Path=GoodsName}"></TextBlock>
</sdk:HierarchicalDataTemplate>
</Grid.Resources>
<sdk:TreeView ItemTemplate="{StaticResource RootTemplate}" Name="tviSample" ItemsSource="{Binding}">
</sdk:TreeView>
</Grid>
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection currentGoods = new ObservableCollection();
currentGoods.Add(new Goods() { GoodsName = "書1", GoodsId = 1 });
currentGoods.Add(new Goods() { GoodsName = "書2", GoodsId = 2 });
currentGoods[0].SubItems.Add(new Goods() { GoodsName = "書11", GoodsId = 11 });
currentGoods[0].SubItems.Add(new Goods() { GoodsName = "書12", GoodsId = 12 });
currentGoods[0].SubItems.Add(new Goods() { GoodsName = "書13", GoodsId = 13 });
tviSample.DataContext = currentGoods;
}
}
public class Goods
{
public string GoodsName { get; set; }
public int GoodsId { get; set; }
public ObservableCollection SubItems { get; set; }
public Goods() { SubItems = new ObservableCollection(); }
public Goods(string GoodsName, int GoodsId):this()
{
this.GoodsId = GoodsId;
this.GoodsName = GoodsName;
}
}
其實(shí)就是為子項(xiàng)的數(shù)據(jù)模板再制定它的子項(xiàng)的數(shù)據(jù)模板,相信讀者如果看懂了上面的代碼,三層,四層什么的,就沒壓力了…但是,如果創(chuàng)建的時(shí)候不知道有多少層,該如何是好?下面便是實(shí)現(xiàn)無限層數(shù)據(jù)顯示的方法:
<sdk:TreeView Name="tviSample" ItemsSource="{Binding}" HorizontalAlignment="Left" VerticalAlignment="Top">
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
<TextBlock Text="{Binding Path=GoodsName}"></TextBlock>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
</sdk:TreeView>
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection currentGoods = new ObservableCollection();
currentGoods.Add(new Goods() { GoodsName = "書1", GoodsId = 1 });
currentGoods.Add(new Goods() { GoodsName = "書2", GoodsId = 2 });
currentGoods[0].SubItems.Add(new Goods() { GoodsName = "書11", GoodsId = 11 });
currentGoods[0].SubItems.Add(new Goods() { GoodsName = "書12", GoodsId = 12 });
currentGoods[0].SubItems.Add(new Goods() { GoodsName = "書13", GoodsId = 13 });
currentGoods[0].SubItems[0].SubItems.Add(new Goods() { GoodsName = "書111", GoodsId = 111 });
currentGoods[0].SubItems[0].SubItems.Add(new Goods() { GoodsName = "書112", GoodsId = 112 });
tviSample.DataContext = currentGoods;
}
}
public class Goods
{
public string GoodsName { get; set; }
public int GoodsId { get; set; }
public ObservableCollection<Goods> SubItems { get; set; }
public Goods() { SubItems = new ObservableCollection(); }
public Goods(string GoodsName, int GoodsId):this()
{
this.GoodsId = GoodsId;
this.GoodsName = GoodsName;
}
}