原文:潜移默化学会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. 那些移动端web踩过的坑2

    原文链接:https://geniuspeng.github.io/2018/04/26/mobile-issues2/ 坑是无穷无尽的,嗯-长江后坑推前坑~~ 关于音频自动播放 H5的audio标签 ...

  2. vs 外部依赖项、附加依赖项以及如何添加依赖项目

    我们在 VS 中创建 Win32 控制台应用程序,vs 会为解决方案创建默认地创建 4 个 filters(资源管理器中没有对应的目录和文件夹): 头文件:一般为 .h 文件 外部依赖项 源文件:一般 ...

  3. How to use ftp in a shell script

    转载How to use ftp in a shell script How to use ftp in a shell script Bruce EdigerBruce Ediger's home ...

  4. runtimeException也是能够捕获的

    如题, 运行结果: bbb abcdef @Test public void testRuntimeException() { ; try { aaa333(); } catch (Exception ...

  5. 怎样用O2O去改变充满谎言、疑虑和愤慨的维修行业

    为什么千亿级的维修服务市场出不了行业巨头?   据相关统计,我国的整个维修服务市场规模可达每年数千亿元之巨(当中仅家电维修就可达近千亿规模,更遑论手机.数码.家具等维修). 相同是千亿级规模的服务行业 ...

  6. Ubuntu su 认证失败

    在使用Ubuntu作为开发环境时经常须要在全局安装一些依赖框架等.这个时候就经常须要用到root权限.可是在Ubuntu下第一次使用su命令时会提示认证失败:查找资料后发现Ubuntu下root权限默 ...

  7. 安装innotop

    安装方法一: 下载地址:https://github.com/innotop/innotop yum install -y perl-TermReadKey yum install -y perl-D ...

  8. Java-Maven项目引入UEditor图片上传组件jar包类库的5种方式

    最近,硬是和百度的UEditor组件杠上了.自己的个人官网项目,很容易就搞定了,公司的项目,尼玛,各种问题.项目多了,环境复杂了,解决问题的方法也得不断调整. 项目用Maven管理jar包,用到了UE ...

  9. Mysql用户本机登陆不成功的解决

    mysql新建一个用户,本机不能登陆,但是远程能够登陆,不知什么原因,最后查阅 http://blog.itpub.net/12679300/viewspace-1453490/ 这篇文章得以解决,进 ...

  10. js进阶 10-7 简单的伪类选择器可以干什么

    js进阶 10-7 简单的伪类选择器可以干什么 一.总结 一句话总结:伪类选择器是冒号. 1.学而不用,有什么用? 多用啊,在项目中多用 2.简单的伪类选择器可以干什么? 除某元素以外,某元素的一切索 ...