原文:潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据

目前自己对treeview的感慨很多

今天先讲 面对这种 表结构的数据 的其中一种绑定方法,后面多几列其他属性都没关系,例如多个字段,

1  A  0

2  B  0

3  C  0

4  D  1

5  E  2

6  F  4

7  G 1

...

就是递归型的表结构

然后通过treeview 展示( treeview 的name 叫 tv , collection 是 ObservableCollection<T> 的 一个实例)

1.首先你必须需要  要建立一个 跟treeview 结构很相似的一个集合,这里建议用  ObservableCollection<T>   这个集合很特殊,你要记得,例如 tv.ItemsSource = this.collection;  当你这样绑定时,修改collection的属性时就是修改treeview绑定的某些属性

2.在做绑定时一定要 搞清楚treeview的item的结构,你想呈现什么样的,每个 treeveiwItem就是一个对象 ,这个对象可以用一个类去替代,或者什么去替代

3. 不啰嗦了,说正题,新建一个实体类

例如

   /// <summary>
////// </summary>
public class ReportCategoryEntity
{
/// <summary>
/// ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Title { get; set; }
/// <summary>
///父节点
/// </summary>
public int ParentID { get; set; } }

这个应该看得懂吧,加入那个递归表 叫 FoodCatagory(菜品目录) 表,现在只要递归显示出来就行了

把他所有行取出来 select * from FoodCatagory,如果其中不止基本的三列,有其他列,例如通过这些列的值  作为控制 treeview显示的样式的条件用 这也是很不错的点子,真的,比如说再加一个图片的地址,如果有个图片地址字典表,这里就存那个表中的字段了,如果其他字段你需要,那你可以继续写在 ReportCategoryEntity 这个类中

读出来的所有行封装到  List<ReportCategoryEntity>    lstReportCategoryEntity  ,这个应该会把,如果不会,说明你的oop基础没学好了

好了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Media; namespace 命名空间
{
public class TreeCategory : INotifyPropertyChanged
{
private ObservableCollection<TreeCategory> children = new ObservableCollection<TreeCategory>(); public TreeCategory() { } public TreeCategory(List<ReportCategoryEntity> totalCategory, int parentID) //0 根目录
{
//Parent = this;
foreach (ReportCategoryEntity item in totalCategory)
{
if (item.ParentID == parentID)
{
TreeCategory tc = new TreeCategory(totalCategory, item.Id);
tc.Title = item.Title;
children.Add(tc);
}
}
} public ObservableCollection<TreeCategory> Children
{
get { return this.children; }
} /// <summary>
/// 显示的名称
/// </summary>
private string title;
public string Title
{
get
{
return title;
}
set
{
title = value;
this.NotifyPropertyChanged("Title");
}
}
/// <summary>
/// 是否选中
/// </summary>
private bool isSelected = false;
public bool IsSelected
{
set
{
this.isSelected = value;
this.NotifyPropertyChanged("IsSelected");
}
get { return this.isSelected; }
} /// <summary>
/// 标题字体颜色
/// </summary>
private Brush foregroundBrush = new SolidColorBrush(Colors.Black);
public Brush ForegroundBrush
{
set
{
this.foregroundBrush = value;
this.NotifyPropertyChanged("ForegroundBrush");
}
get { return this.foregroundBrush; }
} public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
} }
}

接下来再建立一个最重要的 类,用来控制treeview显示的,看似像实体类,但又不像,下面是我建立的,本类下有个本类的集合的属性,还是ObservableCollection集合的,加了 INotifyPropertyChanged 只是为了达到只要修改这个集合的某些属性的值,就可以修改treeview的状态了。

例如我这里添加了 标题字体颜色  ForegroundBrush  这个属性,就是为了达到treeview的每个节点的显示颜色,你在递归的时候就可以根据 ReportCategoryEntity 的某些属性作为条件,然后动态给ForegroundBrush  赋值,要记住,每一个 TreeCategory 类就已经对应了一个 treeviewItem,该类的每一个字段都可以作为 treeview 显示出来的条件,至于前面treeview的样式模板该怎么写,很快你就清楚了

现在说一下 xaml 中前台的写法

 <TreeView Name="tv" Width="" Height="" MaxHeight="" BorderThickness="">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="TreeViewItem.IsExpanded" Value="True"/>
<!--<Setter Property="TreeViewItem.IsSelected" Value="{Binding IsSelected}"/>-->
<!--<EventSetter Event="MouseMove" Handler="tree_MouseMove" />-->
<!--<EventSetter Event="KeyDown" Handler="treeViewItem_KeyDown" />-->
<Setter Property="TreeViewItem.Margin" Value="0,1,0,0"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type c:TreeCategory}" ItemsSource="{Binding Children}">
<StackPanel Margin="-2,0,0,0" Orientation="Horizontal" x:Name="staTree">
<CheckBox Content="{Binding Title}" FontSize="" FontFamily="微软雅黑" Tag="{Binding Children}" IsChecked="{Binding IsSelected}" Foreground="{Binding ForegroundBrush}" Unchecked="ck_Unchecked" Checked="ck_Checked"></CheckBox>
</StackPanel>
<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="true">
<Setter TargetName="staTree" Property="Background" Value="White"/>
</DataTrigger>
</HierarchicalDataTemplate.Triggers>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate> </TreeView>

重点看  <TreeView.ItemTemplate>  这个节点下面的 ,<TreeView.ItemContainerStyle>用来控制总体显示样式的

现在你应该有点清楚了

1. 首先你要知道  treeviewItem 对应一个  TreeCategory ,treeview控件每个节点下都有可能有子节点,像一个集合,所以我在TreeCategory 类中又包括了他自己的一个集合,已达到构造出和treeview很像的一个结构,感觉到了吗

2. ReportCategoryEntity  这个实体是  把从数据库读出来的每条数据的一个net样子,一条表中的数据对应一个 ReportCategoryEntity  实体对象,达到封装效果,不一定只有这三个字段,拓展他以达到treeview显示更丰富的效果,而且treeview的模板很好写,可以改造出很多种

3.就是 TreeCategory 类  ,如果以前没有接触xaml语言的可能会有疑问

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}

为什么会有这堆代码,而且每个属性后面,又调了这个 NotifyPropertyChanged 方法,我不知道原理,但我知道怎么用了,wpf的控件很奇特,不像winform控件或者 asp.net控件那么死,重写个控件很难,这就是为什么wpf 做的桌面软件五花八门,而且很炫,只要你的到控件,不脱离实际,控件都可以变成你想要的控件。又说了好多废话。

最重要的还是我的那个 递归

 public TreeCategory(List<ReportCategoryEntity> totalCategory, int parentID)  //0  根目录
{
//Parent = this;
foreach (ReportCategoryEntity item in totalCategory)
{
if (item.ParentID == parentID)
{
TreeCategory tc = new TreeCategory(totalCategory, item.Id);
//加一些你想要的字段,然后在这里赋值吧
tc.Title = item.Title;
children.Add(tc);
}
}
}

4.为了达到treeview显示的不同效果,加了数据触发器,这样后台一行代码也不要写,有必要的话,你可以再加一个值转换器吧 ,加一些你想要的数据触发器吧,丰富显示效果,例如根据某个字段作为判断条件,如果是什么,把image 控件的source地址换了,就可以达到不同的节点,显示不同的图片了  ,具体应用有很多

<HierarchicalDataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="true">
<Setter TargetName="staTree" Property="Background" Value="White"/>
</DataTrigger>
                    //加一些你想要的数据触发器吧,丰富显示效果,例如根据某个字段作为判断条件,如果是什么,把image 控件的source地址换了,就可以达到不同的节点,显示不同的图片了        
</HierarchicalDataTemplate.Triggers>

后台绑定

    private ObservableCollection<TreeCategory> collection = new ObservableCollection<TreeCategory>();

     this.collection = new TreeCategory(ctagr, ).Children;
treeCategories.ItemsSource = this.collection;
ctagr 是个List<ReportCategoryEntity> 集合

先冒个泡

这是我做的一个菜品目录checkbox多选版本的 ,作为导航栏的,例如选中这个目录,列出这个目录下的所有菜,或者计算出这个菜品目录的菜的销售情况等等,扩展一下,部门与员工是挺经典的一个例子

至于选中根节点,子节点全部选中,那你可以写在checkbox的事件里,应该会吧,这我就不写了,建议递归吧,应为你不知道他下面有多少个子节点

这个我加了checkbox选择的模式,全选,全不选,反选,随选

这个我就再说一点吧,然后来体现ObservableCollection 集合的好处

你不可能修改treeviewItem的属性吧,那个有点傻了

直接修改ObservableCollection 中的 TreeCategory 的IsSelected属性就行了,treeview中自动体现

这里我就只说个全选,全不选 的吧

下面是我写的一个算法

为了防止你粘贴复制,不思考我就上个图吧

反选应该就不用我说了吧,留着思考吧

而且每个 节点的 checkbox都是可以改的,而且你还可以组合控件,例如把很多控件放在stackpanel 中,作为一个treeviewItem

例如每个节点鼠标移上去的效果你都可以很轻松的改的,就看你的技术了,鼠标移上去,我就不说了

再看个图吧

如果你熟悉treeview的话,迅雷看看的这个目录效果很轻松的可以做出来,那个TreeviewItem加载动画也可以做

,这是个 目录下有具体内容的treeview结构,这个如果也用这种MVVM思想的话也可以很轻松的做出来,我做过,多态做的,呵呵,下次有时间的话就再写篇 treeview下面有内容时,该怎么写。

我自己感觉迅雷看看有点像 Expander 加 treeview  控件呢?下次做一个迅雷看看左边的目录 制作教程吧,好了,就暂时啰嗦到这里吧

潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据的更多相关文章

  1. WPF常用控件应用demo

    WPF常用控件应用demo 一.Demo 1.Demo截图如下: 2.demo实现过程 总体布局:因放大缩小窗体,控件很根据空间是否足够改变布局,故用WrapPanel布局. <ScrollVi ...

  2. 潜移默化学会WPF(绚丽篇)--热烈欢迎RadioButton,改造成功,改造成ImageButton,新版导航

    原文:潜移默化学会WPF(绚丽篇)--热烈欢迎RadioButton,改造成功,改造成ImageButton,新版导航 本样式 含有  触发器 和 动画    模板  ,多条件触发器,还有布局 本人博 ...

  3. WPF Popup 控件导致被遮挡内容不刷新的原因

    WPF Popup 控件导致被遮挡内容不刷新的原因 周银辉 今天在写一个WPF控件时用到了Popup控件,很郁闷的情况是:当popup关闭时,原来被popup挡住的界面部分不刷新,非要手动刷新一下(比 ...

  4. 创建 WPF 工具箱控件

    创建 WPF 工具箱控件 WPF (Windows Presentation Framework) 工具箱控件模板允许您创建 WPF 控件,会自动添加到 工具箱 安装扩展的安装. 本主题演示如何使用模 ...

  5. wpf打印控件 实现分页打印控件功能

    因为 要实现打印 wpf  listbox控件  数据特别多 要打印在 几张纸上    找了几天 都没有找到相关的例子 现在 解决了 在这里和大家分享一下 public void print(Fram ...

  6. WPF 分页控件 WPF 多线程 BackgroundWorker

    WPF 分页控件 WPF 多线程 BackgroundWorker 大家好,好久没有发表一篇像样的博客了,最近的开发实在头疼,很多东西无从下口,需求没完没了,更要命的是公司的开发从来不走正规流程啊, ...

  7. WPF Image控件中的ImageSource与Bitmap的互相转换

    原文:WPF Image控件中的ImageSource与Bitmap的互相转换  1.从bitmap转换成ImageSource [DllImport("gdi32.dll", ...

  8. 【转】WPF - 第三方控件

    WPF - 第三方控件 目前第三方控件在网上形成巨大的共享资源,其中包括收费的也有免费的,有开源的也有不开源的,合理的使用第三方控件将使项目组的工作事半功倍.比如项目中有些复杂的业务逻辑.有些绚丽的效 ...

  9. WPF布局控件与子控件的HorizontalAlignment/VerticalAlignment属性之间的关系

    WPF布局控件与子控件的HorizontalAlignment/VerticalAlignment属性之间的关系: 1.Canvas/WrapPanel控件: 其子控件的HorizontalAlign ...

随机推荐

  1. CAP理论/AP架构/CP架构

      原文地址:https://blog.csdn.net/u013058742/article/details/83541905  简书里的文章:Spring Cloud Eureka简介及与Zook ...

  2. phoenixframe平台连接socketserver,并接收返回值的演示样例

    package org.phoenix.cases.webservice; import java.util.LinkedList; import org.phoenix.action.WebElem ...

  3. openstack中虚拟机怎么与物理机通信

    How-to-connection-ns-outside 环境配置 网络接口 vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 TYPE ...

  4. JS和PHP和JAVA的正则表达式的区别(java没有分解符,java中的转义字符是\\)

    JS和PHP和JAVA的正则表达式的区别(java没有分解符,java中的转义字符是\\) 一.总结 js正则:var patrn=/^[0-9]{1,20}$/; php正则:$pattern='/ ...

  5. [RxJS] Split an RxJS Observable into groups with groupBy

    groupBy() is another RxJS operator to create higher order observables. In this lesson we will learn ...

  6. web网站如何实现兼容手机

    web网站如何实现兼容手机 一.总结 一句话总结:加上这句话即可:<meta name="viewport" content="width=device-width ...

  7. js进阶正则表达式14验证邮编(input的pattern属性)(正则表达式加起^始$)

    js进阶正则表达式14验证邮编(input的pattern属性)(正则表达式加起^始$) 一.总结 1.input的pattern属性:里面可以直接放正则表达式,<input type=&quo ...

  8. 开源 免费 java CMS - FreeCMS1.9 会员管理

    项目地址:http://www.freeteam.cn/ 会员管理 1. 会员管理 从左側管理菜单点击会员管理进入. 2. 加入会员 在会员列表下方点击"加入"button. 填写 ...

  9. php标准库中的优先队列SplPriorityQueue怎么使用?(继承)

    php标准库中的优先队列SplPriorityQueue怎么使用?(继承) 一.总结 1.new对象,然后通过insert方法和extract方法来使用,top方法也很常用. 2.类的话首先想到继承, ...

  10. 自旋锁解决StackOverflowError案例

    本节笔者分享一个在实际工作中遇到的栈内存溢出(StackOverflowError)问题,以及其解决方案. 问题介绍:笔者负责的一个Java Web项目在启动的时候,需要有一些初始化操作,而接下来的代 ...