潜移默化学会WPF(难点控件treeview)--改造TreeView(CheckBox多选择版本),递归绑定数据
原文:潜移默化学会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多选择版本),递归绑定数据的更多相关文章
- WPF常用控件应用demo
WPF常用控件应用demo 一.Demo 1.Demo截图如下: 2.demo实现过程 总体布局:因放大缩小窗体,控件很根据空间是否足够改变布局,故用WrapPanel布局. <ScrollVi ...
- 潜移默化学会WPF(绚丽篇)--热烈欢迎RadioButton,改造成功,改造成ImageButton,新版导航
原文:潜移默化学会WPF(绚丽篇)--热烈欢迎RadioButton,改造成功,改造成ImageButton,新版导航 本样式 含有 触发器 和 动画 模板 ,多条件触发器,还有布局 本人博 ...
- WPF Popup 控件导致被遮挡内容不刷新的原因
WPF Popup 控件导致被遮挡内容不刷新的原因 周银辉 今天在写一个WPF控件时用到了Popup控件,很郁闷的情况是:当popup关闭时,原来被popup挡住的界面部分不刷新,非要手动刷新一下(比 ...
- 创建 WPF 工具箱控件
创建 WPF 工具箱控件 WPF (Windows Presentation Framework) 工具箱控件模板允许您创建 WPF 控件,会自动添加到 工具箱 安装扩展的安装. 本主题演示如何使用模 ...
- wpf打印控件 实现分页打印控件功能
因为 要实现打印 wpf listbox控件 数据特别多 要打印在 几张纸上 找了几天 都没有找到相关的例子 现在 解决了 在这里和大家分享一下 public void print(Fram ...
- WPF 分页控件 WPF 多线程 BackgroundWorker
WPF 分页控件 WPF 多线程 BackgroundWorker 大家好,好久没有发表一篇像样的博客了,最近的开发实在头疼,很多东西无从下口,需求没完没了,更要命的是公司的开发从来不走正规流程啊, ...
- WPF Image控件中的ImageSource与Bitmap的互相转换
原文:WPF Image控件中的ImageSource与Bitmap的互相转换 1.从bitmap转换成ImageSource [DllImport("gdi32.dll", ...
- 【转】WPF - 第三方控件
WPF - 第三方控件 目前第三方控件在网上形成巨大的共享资源,其中包括收费的也有免费的,有开源的也有不开源的,合理的使用第三方控件将使项目组的工作事半功倍.比如项目中有些复杂的业务逻辑.有些绚丽的效 ...
- WPF布局控件与子控件的HorizontalAlignment/VerticalAlignment属性之间的关系
WPF布局控件与子控件的HorizontalAlignment/VerticalAlignment属性之间的关系: 1.Canvas/WrapPanel控件: 其子控件的HorizontalAlign ...
随机推荐
- LIGO找到首个超越广义相对论的证据?
转自 麻省理工科技评论 原文 LIGO找到首个超越广义相对论的证据? 1915年,爱因斯坦根据简单的原理提出广义相对论,极大地改变了人们的时空观.广义相对论不仅解释了牛顿理论无法解释的现象,还做出许多 ...
- [Angular2 Router] Get activated router url
getActivatedRoutePath(r: ActivatedRoute) { return r.url .subscribe(p => this.curtPath = p[0].path ...
- ASP.NET MVC中实现多个button提交的几种方法
有时候会遇到这样的情况:在一个表单上须要多个button来完毕不同的功能,比方一个简单的审批功能. 假设是用webform那不须要讨论,但asp.net mvc中一个表单仅仅能提交到一个Action处 ...
- php面试题7(1、unset变量是删除栈变量,并不删除堆变量)(2、php爬虫特别简单: 可以file_get_contents和直接fopen)
php面试题7(1.unset变量是删除栈变量,并不删除堆变量)(2.php爬虫特别简单: 可以file_get_contents和直接fopen) 一.总结 1.unset变量是删除栈变量,并不删除 ...
- android,安卓get请求的提交以及我遇到的异常
首先说明 我是安卓4.0以上的版本,这个时候直接用网上的代码会报错的,先赋上网上的普遍代码 String uri = "http://url"; HttpGet httpGet = ...
- QQ互联API接口失效,第三方网站的死穴
最近2个月,用开源程序WeCenter搭建了一个社交问答网站. 为了方便用户注册,开通了QQ登录功能. 今天,突然发现QQ互联返回一直出现错误. 度娘了很久,发现大家都遇到这个问题了.Disc ...
- oracle 基础表 mysql版
emp 员工表(empno 员工号/ename 员工姓名/job 工作/mgr 上级编号/hiredate 受雇日期/sal 薪金/comm 佣金/deptno 部门编号) dept 部门表(dept ...
- hadoop集群ambari搭建(1)之ambari-server安装
Apache Ambari是一种基于Web的工具,支持Apache Hadoop集群的供应.管理和监控. Ambari眼下已支持大多数Hadoop组件,包含HDFS.MapReduce.Hive.Pi ...
- html5-4 HTML5超链接、URL地址和表格
html5-4 HTML5超链接.URL地址和表格 一.总结 一句话总结: 1.cellspace有什么用? 清除表格的单元格间距 26 <table border='1px' cellspac ...
- jquery-3 jquery选择器
jquery-3 jquery选择器 一.总结 一句话总结:选择器使用的时候可以结合参考手册,里面都已经详细归类好了.(多用才能熟啊) 1.$(:input).css({'color':'#98765 ...