最近接手WPF的项目,从0开始,做些积累
Demo地址:https://github.com/AlbinZhang/WPF_Pratice.git 里面的001_TreeView_Model
0.效果图
1. TreeView使用模版
参考链接:
Treeview - http://www.cnblogs.com/_ymw/p/3450345.html
HierarchicalDataTemplate - http://www.cnblogs.com/goldren/archive/2012/12/11/2812697.html
HierarchicalDataTemplate顾名思义,分层数据模板,就是用来定义分层数据样式的模板,一般多用于MenuItem和TreeViewItem
DataType指定模板用于哪种数据类型
ItemsSource指定该类数据的子集,即下一层显示那些数据
内容 指定数据如何显示 绑定哪个属性
//-------XMAL
xmlns:local="clr-namespace:_001_TreeView_Model"
<Grid.Resources>
<HierarchicalDataTemplate x:Key="TreeTemplate" DataType="{x:Type local:Node}" ItemsSource="{Binding Nodes}">
<StackPanel Orientation="Horizontal" Margin="2,3,2,3" >
<Image Source="{Binding Image}" Width="18" Height="18" Margin="0,0,5,0" />
<CheckBox Margin="0, 5" IsChecked="{Binding bClick}" ></CheckBox>
<Label Content="{Binding Name}"/>
</StackPanel>
</HierarchicalDataTemplate>
</Grid.Resources>
<TreeView Name="tvTreeView" Grid.Column="0" ItemTemplate="{StaticResource TreeTemplate}">
//--------Code
List<Node> outputList = new List<Node>();
tvTreeView.ItemsSource = outputList;
public class Node
{
public Node()
{
this.Nodes = new List<Node>();
this.ParentID = -1;
this.Image = "D:/Code/C#/001_TreeView_Model/001_TreeView_Model/link.png";
}
public int ID { get; set; }
public string Name { get; set; }
public string Image { get; set; }
public bool bClick { get; set; }
public int ParentID { get; set; }
public List<Node> Nodes { get; set; }
}
2.点击checkBox获取当前TreeViewItem的DataContent
这个需要先从视觉树上获取到TreeViewItem
下面是打印当前视觉树的函数,先知道树什么样才能取
string treeStr = "";
void printVisualTree(int depth, DependencyObject obj)
{
treeStr += new string(' ', depth) + obj + "\r\n"; //打印空格,方便查看
//递归打印视觉树
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
printVisualTree(depth + 1, VisualTreeHelper.GetChild(obj, i));
}
}
利用上面的打印函数,打印 TreeView 的视觉树,然后确定怎么获取到TreeViewItem的对象
printVisualTree(0, tvTreeView);
///////////////
System.Windows.Controls.TreeView Items.Count:1
System.Windows.Controls.Border
System.Windows.Controls.ScrollViewer
System.Windows.Controls.Grid
System.Windows.Shapes.Rectangle
System.Windows.Controls.ScrollContentPresenter
System.Windows.Controls.ItemsPresenter
System.Windows.Controls.StackPanel
System.Windows.Controls.TreeViewItem 标题:_001_TreeView_Model.Node Items.Count:3
System.Windows.Controls.Grid
System.Windows.Controls.Primitives.ToggleButton 内容: IsChecked:False
System.Windows.Controls.Border
System.Windows.Shapes.Path
System.Windows.Controls.Border
System.Windows.Controls.ContentPresenter
System.Windows.Controls.StackPanel
System.Windows.Controls.Image
System.Windows.Controls.CheckBox 内容: IsChecked:True
System.Windows.Controls.Grid
System.Windows.Controls.Border
System.Windows.Controls.Grid
System.Windows.Shapes.Path
System.Windows.Shapes.Rectangle
System.Windows.Controls.ContentPresenter
System.Windows.Controls.Label: 中国
System.Windows.Controls.Border
System.Windows.Controls.ContentPresenter
System.Windows.Controls.TextBlock
System.Windows.Controls.ItemsPresenter
System.Windows.Documents.AdornerLayer
System.Windows.Controls.Primitives.ScrollBar 最小值:0 最大值:0 值:0
System.Windows.Controls.Primitives.ScrollBar 最小值:0 最大值:0 值:0
使用下面函数获取TreeViewItem
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox cb = sender as CheckBox;
TreeViewItem Item = (TreeViewItem)VisualUpwardSearch<TreeViewItem>(cb);
Node node = Item.DataContext as Node;
MessageBox.Show(string.Format("{0} is Click({1})", node.Name, node.bClick));
}
DependencyObject VisualUpwardSearch<T>(DependencyObject source) //搜寻可视话树的父节点
{
while (source != null && source.GetType() != typeof(T))
source = VisualTreeHelper.GetParent(source);
return source;
}
3. TreeViewItem绑定MouseLeftButtonDown 事件,并使其生效
参考连接:http://stackoverflow.com/questions/30356236/mouseleftbuttondown-event-not-raised-in-treeviewitem-why
首先通过style的方式给TreeViewItem绑定上MouseLeftButtonDown事件,并且直接绑定鼠标事件是不响应的,
stackoverflow上的说法是在TreeViewItem中的TreeViewItem.OnMouseLeftButtonDown事件在Item获取到焦点的时候,
事件就已经被标记了,然后LeftButtonDown就获取不到事件,所以无法响应
只要先不让TreeViewItem的获取到焦点,LeftButtonDown就获取到事件了 (不知道多少把刀的水平,勿喷,建议直接看链接)
//---------XMAL
<TreeView Name="tvTreeView" Grid.Column="0" ItemTemplate="{StaticResource TreeTemplate}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Setters>
<Setter Property="Focusable" Value="False"/> <!-- 就是使当前item不能获取焦点 -->
<EventSetter Event="MouseLeftButtonDown" Handler="tvTreeViewItem_MouseLeftButtonDown" />
</Style.Setters>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
//----------Code
private void tvTreeViewItem_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("TreeViewItem MouseLeftButtonDown");
TreeViewItem item = sender as TreeViewItem;
//下面部分是可以让item临时获取焦点,UI上有选中的效果
item.Focusable = true;
item.Focus();
item.Focusable = false;
e.Handled = true;
}
4. 收缩所有子节点
private void Contract_Click(object sender, RoutedEventArgs e)
{
TreeViewItem root = (TreeViewItem)tvTreeView.ItemContainerGenerator.ContainerFromIndex(0);
if (root != null)
{
CollapseTreeviewItems(root);
}
}
private void CollapseTreeviewItems(TreeViewItem Item)
{
Item.IsExpanded = false;
foreach (var item in Item.Items)
{
DependencyObject dObject = tvTreeView.ItemContainerGenerator.ContainerFromItem(item);
if (dObject != null)
{
((TreeViewItem)dObject).IsExpanded = false;
if (((TreeViewItem)dObject).HasItems)
{
CollapseTreeviewItems(((TreeViewItem)dObject));
}
}
}
}