您的位置:首页 > 其它

如何实现具有层次结构的 TreeView <三> (WPF/TreeView/Style/Template)

2011-08-05 08:44 573 查看
数据模板 (DataTemplate) 和数据绑定 (Data Binding)

为了把数据和界面进行关联,我们要做 3 件事:

1、在 MainWindow.xaml 中添加一个 TreeView 控件

<TreeView x:Name="tv">
</TreeView>


2、将数据绑定到 TreeView 控件上

在 WPF 中实现数据绑定的方法主要有2种: 在 XAML 中声明或在 Code 中指定。详细信息请参考 MSDN:
Windows Presentation Foundation 数据绑定 <一>
Windows Presentation Foundation 数据绑定 <二>

由于此处的 TreeView 顶层节点需要 ParentID 为 NULL 的数据,所以我采用了在 Code 中指定的方式。
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();

// 添加 MainWindow.Loaded 事件
this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
}

private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// 在代码中为 TreeView 控件设置 ItemsSource 属性
var dc = new CSDNBlogDataContext();
var items = dc.Departments.Where(item => item.ParentID == null);
tv.ItemsSource = items.ToArray();
}
}


关于 LINQ 请参考 MSDN:

LINQ 查询表达式 (C# 编程指南)

101 LINQ Samples

完成以上工作并运行程序,将看到类似下图中显示的界面:



从上面的图片可以看出,每一个 ListViewItem 都绑定了一个 Department 对象,由于我们尚未告诉 ListViewItem 如何显示 Department 对象的内容(即属性),所以系统默认分配了一个 TextBlock 控件,并将 Department.ToString() 的信息给呈现了出来。那 Department 的对象内容该如何显示呢?

3、为 TreeView 控件添加数据模板 (DataTemplate)

数据模板 (DataTemplate 类) 用于描述数据对象的可视化结构。

打个比方,当前工程中用到的数据对象是 Department,而每个 Department 都拥有4个属性: DepartmentID、ParentID、Name 和 Type。当我们将每个 Department 与 TreeViewItem 进行关联(即数据绑定)之后,我们应该告诉 TreeViewItem 如何呈现与其关联的 Department 对象,简单理解就是如何显示 Department 的那4个属性。而 DataTemplate 就是用来定义这个结构的东东。

通常,描述数据对象的可视化结构,直接使用 DataTemplate 就可以了。但是当前工程中的 Department 是可以包含“子部门”的数据项,而且其深度未知。所以,此处使用的是 HierarchicalDataTemplate 类,即允许包含“子数据项”的 DataTemplate.

例如:

a、使用一个
TextBlock 对象,仅用于呈现与该 ListViewItem 关联的 Department 对象的 Name 属性

<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>




b、稍微复杂一点的结构,呈现 Name(Type) 形式的2个属性。

<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
<!--<TextBlock Text="{Binding Path=Name}"/>-->
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}"/>
<TextBlock Text="("/>
<TextBlock Text="{Binding Path=Type}"/>
<TextBlock Text=")"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>




通过上面2个简单的示例,我们应该对 DataTemplate 是如何描述数据对象的可视化结构有了一个直观的了解。

接下来,将介绍如何实现文本的纵向显示,这里有个概念需要先说明下:

一个字符串 (String) 可以被看作是一个字符数组 (Char[])

根据这一特性,我们可以将一个字符串作为数据源绑定到某个支持 ItemsSource 或 IsItemsHost 属性的控件上。例如: 将 Name 属性指定给 StackPanel、Grid、ListBox 或者 ItemsControl 等对象。

同时,基于 WPF 的数据转换规则,该字符串中的每个 Char 对象都将被自动转换为 String 对象输出到用户界面。

根据上述特征,修改一下 DataTemplate 就能实现文本的纵向显示了:

<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children}">
<!--<TextBlock Text="{Binding Path=Name}"/>-->
<!--<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}"/>
<TextBlock Text="("/>
<TextBlock Text="{Binding Path=Type}"/>
<TextBlock Text=")"/>
</StackPanel>-->
<ItemsControl ItemsSource="{Binding Path=Name}">
<ItemsControl.Style>
<Style TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Grid>
<ItemsPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ItemsControl.Style>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="block" RenderTransformOrigin="0.5,0.5" Text="{Binding}" TextAlignment="Center"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding}" Value="(">
<Setter TargetName="block" Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="90"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding}" Value=")">
<Setter TargetName="block" Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="90"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding}" Value="-">
<Setter TargetName="block" Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="90"/>
</Setter.Value>
</Setter>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>




此时,数据绑定和数据模板定义已经完成。下一节将介绍:

1、如何布局 TreeView 控件,实现节点的横向排列 (从左到右,自上而下) 的视图。

2、为 TreeViewItem 设置控件模板 (ControlTemplate) 和触发器 (Trigger),令其在不同状态下呈现出不同的颜色、边框及背景等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: