WPF TreeView DataTableバインドによる無限層フィルタリング

23887 ワード

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