WPF TreeView DataTable 绑定 实现无限层过滤
时间:2012-02-24 19:48
来源:博客园
作者:sliphades
点击: 166次
WPF 树绑定,确实不容易,如果思路停留在以前WinForm,Asp.net 上面就会很吃力,要转变为MVVM思想,开发起来才会得心应手,我写这篇文章的目的不在于建议使用DataTable 直接来绑定TreeView,而是想通过此文给予误入WPF误区的青年(just like me)给予一些帮助,最终我还是使用MVVM模式来完成了WPF中TreeView 的绑定。 废话不
WPF 树绑定,确实不容易,如果思路停留在以前WinForm,Asp.net 上面就会很吃力,要转变为MVVM思想,开发起来才会得心应手,我写这篇文章的目的不在于建议使用DataTable 直接来绑定TreeView,而是想通过此文给予误入WPF误区的青年(just like me)给予一些帮助,最终我还是使用MVVM模式来完成了WPF中TreeView 的绑定。
废话不多说,表数据如下
F_ID | F_ParentID | F_Name | F_Remark |
2b632e6f-358c-4ba7-bdd9-fb0777ee6695 | NULL | 学历 | 描述人员学历 |
3a809712-4773-4fcf-b568-fcd9c52dbe56 | 2b632e6f-358c-4ba7-bdd9-fb0777ee6695 | 本科 | NULL |
934d23ca-2c56-4108-971f-79a786e4db71 | 2b632e6f-358c-4ba7-bdd9-fb0777ee6695 | 专科 | NULL |
7a9b3891-e5d9-4649-824d-984db88d9ad4 | 2b632e6f-358c-4ba7-bdd9-fb0777ee6695 | 高中 | NULL |
主要功能实现用户输入关键字,TreeView 根据关键字(按照树节点名称拼音)过滤树节点。
取出表数据存放于DataSet中的DataTable里面,我们要设置其关系(当让如果你用Typed DataSet 可以直接用IDE画出来),让系统知道这个是个树型结构。
核心代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace WPFTreeViewDataTableDemo
{
/// <summary>
/// WPF TreeView DataTable 绑定对象
/// </summary>
public class WPFTreeViewBind
{
/// <summary>
/// 主要是用作 TreeView 数据源显示
/// </summary>
public DataView RootNodes
{
set;
get;
}
String BaseFilter
{
get;
set;
}
public String FilterColumn
{
get;
set;
}
public Predicate<String> CustomFiler
{
get;
set;
}
/// <summary>
/// 组织 DataTable 形成树状结构
/// </summary>
/// <param name="TreeDB">数据源DataSet</param>
/// <param name="IDColumn">ID列</param>
/// <param name="ParentColumn">父ID列</param>
/// <param name="ParentIDFilter">过滤字符(满足我们实体表中F_ParentID =1 或者 -1 或者 "" 等情况)</param>
public void InitTreeViewDataSet(DataSet TreeDB, String IDColumn, String ParentColumn, String RootParentID)
{
//TreeDB.Tables[0].TableName = "Master";
///添加一个逻辑列,用来过滤
TreeDB.Tables["Master"].Columns.Add("Flag", typeof(bool));
//添加父子关系(注意添加一列逻辑列用来过滤使用)两个条件作为 AND 使用关于表关系可以参考DataTable Relations
TreeDB.Relations.Add("TreeChild",
new DataColumn[] { TreeDB.Tables["Master"].Columns[IDColumn], TreeDB.Tables["Master"].Columns["Flag"] },
new DataColumn[] { TreeDB.Tables["Master"].Columns[ParentColumn], TreeDB.Tables["Master"].Columns["Flag"] }, false);
//再次添加父子关系,不关联逻辑列
TreeDB.Relations.Add("TreeParentChild",
new DataColumn[] { TreeDB.Tables["Master"].Columns[IDColumn], },
new DataColumn[] { TreeDB.Tables["Master"].Columns[ParentColumn], }, false);
//我们要显示的就是RootNode
RootNodes = TreeDB.Tables["Master"].DefaultView;
//初始化DataTable 逻辑列
foreach (DataRow dr in RootNodes.Table.Rows)
{
dr.SetField("Flag", true);
}
//初始化过滤列模式(用于完成满足我们实体表中F_ParentID =1 或者 -1 或者 "" 等情况)
String TypeOFLink = String.Empty;
if (String.Compare(RootParentID, "NULL", false) == 0)
{
TypeOFLink = " Is ";
}
else
{
TypeOFLink = " = ";
}
BaseFilter = "(" + ParentColumn + TypeOFLink + RootParentID + ") " + " AND (Flag = True)";
RootNodes.RowFilter = BaseFilter;
}
/// <summary>
/// 设置过滤器(利用DataView 过滤功能)
/// </summary>
/// <param name="_filterString">过滤关键字</param>
public void SetFilter()
{
foreach (DataRow dr in RootNodes.Table.Rows)
{
if (String.IsNullOrEmpty(FilterColumn))
{
dr.SetField("Flag", true);
}
else
{
dr.SetField("Flag", false);
}
}
foreach (DataRow dr in RootNodes.Table.Rows)
{
if (this.CustomFiler(dr[FilterColumn].ToString()))
{
dr.SetField("Flag", false);
}
}
foreach (DataRow dr in RootNodes.Table.Rows)
{
if (this.CustomFiler(dr[FilterColumn].ToString()))
{
dr.SetField("Flag", true);
this.SetParent(dr, true);
}
}
RootNodes.RowFilter = BaseFilter;
}
/// <summary>
/// 设置父数据
/// </summary>
/// <param name="dr"></param>
/// <param name="p"></param>
private void SetParent(DataRow dr, bool p)
{
if (dr.GetParentRow("TreeParentChild") != null)
{
dr.GetParentRow("TreeParentChild").SetField("Flag", p);
SetParent(dr.GetParentRow("TreeParentChild"), p);
}
}
}
}
前台调用
using System;
using System.Windows.Controls;
using WPFTreeViewDataTableDemo.DB;
using WPFTreeViewDataTableDemo.DB.DatabaseDataSetTableAdapters;
using System.Data;
namespace WPFTreeViewDataTableDemo
{
/// <summary>
/// demoMain.xaml 的交互逻辑
/// </summary>
public partial class demoMain : Page
{
WPFTreeViewBind WVB;
DataSet OperatorDataSet;
public demoMain()
{
InitializeComponent();
T_BaseCodeTableAdapter filler = new T_BaseCodeTableAdapter();
DatabaseDataSet DB = new DatabaseDataSet();
filler.Fill(DB.T_BaseCode);
WVB = new WPFTreeViewBind();
//此处我使用强类型仅作为一个演示,操作普通类型 DataTable.当然你可以直接返回你类型化的DataSet(DB.T_BaseCode)
DataTable OperatorTabel = DB.T_BaseCode.DefaultView.ToTable("Master");
OperatorDataSet = new DataSet();
OperatorDataSet.Tables.Add(OperatorTabel);
WVB.InitTreeViewDataSet(OperatorDataSet, "F_ID", "F_ParentID", "NULL");
WVB.FilterColumn = "F_Name";
WVB.CustomFiler = CustomFilter;
tree.DataContext = WVB;
}
String FilterString;
Boolean CustomFilter(object sender)
{
return sender.ToString().GetChineseSpell(false).Contains(FilterString);
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox Tb =sender as TextBox;
FilterString= Tb.Text.Trim();
WVB.SetFilter();
}
}
}
XAML
<Page x:Class="WPFTreeViewDataTableDemo.demoMain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="demoMain">
<Grid>
<StackPanel Orientation="Vertical">
<GroupBox Header="检索过滤">
<TextBox TextChanged="TextBox_TextChanged"></TextBox>
</GroupBox>
<TreeView Name="tree" ItemsSource="{Binding RootNodes }">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding TreeChild}">
<TextBlock Text="{Binding F_Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Grid>
</Page>
最终实现如图:
未过滤 | 已过滤
|
![]() | |
![]() | 源码下载 |
本文来自sliphades的博客,原文地址:http://www.cnblogs.com/peerlesssoul/articles/2350085.html