数据绑定:

更新内容:补充在MVVM模式上的TreeView控件数据绑定的代码。

xaml代码:

<TreeView Name="syntaxTree" ItemsSource="{Binding TreeNodes}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:TreeNode}" ItemsSource="{Binding Path=ChildNodes}">
<TextBlock Text="{Binding NodeName}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

TreeView中的ItemsSource绑定的是一个名为TreeNodes的TreeNode的列表,即List<TreeNode>TreeNodes。HierarchicalDataTemplate中的ItemsSource绑定的TreeNodes中的每个节点的ChildNodes属性。

ViewModel.cs中的代码(有删减):

public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private List<TreeNode> treenodes = new List<TreeNode>();
public List<TreeNode> TreeNodes
{
get { return treenodes; }
set
{
treenodes = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("TreeNodes"));
}
} public ViewModel()
{
    // Nodes是我已经获得的一组节点
TreeNodes = getChildNodes(0,Nodes);
} private List<TreeNode> getChildNodes(int parentID, List<TreeNode> nodes)
{
List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
List<TreeNode> otherNodes = nodes.Where(x => x.ParentID != parentID).ToList();
foreach (TreeNode node in mainNodes)
node.ChildNodes = getChildNodes(node.NodeID, otherNodes);
return mainNodes;
}
}

使用MVVM模式,那么xaml.cs文件就会变得非常简单了,基本只有一句代码了:

this.DataContext = new ViewModel();

该模式的好处就是使得UI设计和后端代码分开,只通过数据绑定进行连接。尝试用了几次,真的还蛮方便。


TreeView数据绑定需要使用层次结构数据模板(HierarchicalDataTemplate)来显示分层数据。XAML代码如下:

<TreeView Name="chapterTree" Grid.Column="0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=ChildNodes}">
<StackPanel>
<Label Content="{Binding Path=NodeName}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>

其中,ItemsSource绑定的对象ChildNodes应该是一个集合类型:List<TreeNode>,Label中绑定的是TreeNode的NodeName属性,TreeNode类定义如下所示:

public class TreeNode
{
public int NodeID { get; set; }
public int ParentID { get; set; }
public string NodeName { get; set; }
public List<TreeNode> ChildNodes { get; set; }
public TreeNode()
{
ChildNodes = new List<TreeNode>();
}
}

因为是树形结构,因此TreeNode需要有NodeID属性和ParentID属性,即某个树节点node本身的ID和它所属的父节点的ID。以目录为例,则xaml.cs中的代码如下。首先是写入了数据,在我实际项目中,这些数据是从DB中查询的,这里为了简化,直接Input数据了。

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InputData();
chapterTree.ItemsSource = getNodes(0, nodes);
} private List<TreeNode> nodes;
private void InputData()
{
nodes = new List<TreeNode>()
{
new TreeNode(){ParentID=0, NodeID=1, NodeName = "Chapter1" },
new TreeNode(){ParentID=0, NodeID=2, NodeName="Chapter2"},
new TreeNode(){ParentID=0,NodeID=3, NodeName="Chapter3"},
new TreeNode(){ParentID=1, NodeID=4, NodeName="Section1.1"},
new TreeNode(){ParentID=1, NodeID=5, NodeName="Section1.2"},
new TreeNode(){ParentID=2, NodeID=6, NodeName="Section2.1"},
new TreeNode(){ParentID=3, NodeID=7, NodeName="Section3.1"},
new TreeNode(){ParentID=6, NodeID=8, NodeName="SubSection2.1.1"},
new TreeNode(){ParentID=6, NodeID=9, NodeName="SubSection2.1.2"},
new TreeNode(){ParentID=2, NodeID=10,NodeName="Section2.2"},
new TreeNode(){ParentID=3, NodeID=11, NodeName="Section3.2"}
};
}
private List<TreeNode> getNodes(int parentID, List<TreeNode> nodes)
{
List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
List<TreeNode> otherNodes = nodes.Where(x => x.ParentID != parentID).ToList();
foreach (TreeNode node in mainNodes)
node.ChildNodes = getNodes(node.NodeID, otherNodes);
return mainNodes;
}
}

需要注意的就是NodeID是不断增加的,每个节点都有自己的ID,而其ParentID就看它是属于哪个父节点的了。getNodes()是一个递归方法,就是不断读取某个节点的子节点。运行结果如图所示:

后台动态添加TreeView:

一开始,没用数据绑定,就直接在xaml.cs中使用treeview,虽然后来用了数据绑定之后发现还是绑定更方便,但是这种在后台构建treeview的方法没准哪天也能用到,就记录一下吧。

XAML文件,使用一个TreeView控件

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60*"/>
<ColumnDefinition Width="100*"/>
</Grid.ColumnDefinitions>
<TreeView Name="chapterTree" Grid.Column="0"/>
</Grid>

XAML.CS文件,同样使用递归方法,就是不断的新建treeviewitem控件。

public partial class DynamicTreeView : Window
{
public DynamicTreeView()
{
InitializeComponent();
InputData();
ShowTreeView();
} private List<TreeNode> nodes;
private void InputData()
{
nodes = new List<TreeNode>()
{
new TreeNode(){ParentID=0, NodeID=1, NodeName = "Chapter1" },
new TreeNode(){ParentID=0, NodeID=2, NodeName="Chapter2"},
new TreeNode(){ParentID=0,NodeID=3, NodeName="Chapter3"},
new TreeNode(){ParentID=1, NodeID=4, NodeName="Section1.1"},
new TreeNode(){ParentID=1, NodeID=5, NodeName="Section1.2"},
new TreeNode(){ParentID=2, NodeID=6, NodeName="Section2.1"},
new TreeNode(){ParentID=3, NodeID=7, NodeName="Section3.1"},
new TreeNode(){ParentID=6, NodeID=8, NodeName="SubSection2.1.1"},
new TreeNode(){ParentID=6, NodeID=9, NodeName="SubSection2.1.2"},
new TreeNode(){ParentID=2, NodeID=10,NodeName="Section2.2"},
new TreeNode(){ParentID=3, NodeID=11, NodeName="Section3.2"}
};
} private void ShowTreeView()
{
TreeViewItem tv1 = new TreeViewItem();
chapterTree.Items.Add(tv1);
GetNodes(0, tv1);
} private void GetNodes(int parentID, TreeViewItem tv)
{
List<TreeNode> mainNodes = nodes.Where(x => x.ParentID == parentID).ToList();
foreach(var item in mainNodes)
{
TreeViewItem tv1 = new TreeViewItem();
tv1.Header = item.NodeName;
tv.Items.Add(tv1);
GetNodes(item.NodeID, tv1);
}
}
}

运行图:总归是没有databinding方便。刚开始学习WPF,一开始没想过要用数据绑定,总感觉只要能实现自己想要的东西就可以了,不用管实现过程,后来使用了之后发现,使用数据绑定构建MVVM架构的应用还是挺好的。

第二部分将总结给节点添加事件的方法。

https://www.cnblogs.com/larissa-0464/p/12441607.html

关于TreeView控件的demo:

WPF中常用控件(TreeView, ComboBox, DataGrid, ListView)使用MVVM模式绑定的demo - 南风小斯 - 博客园 (cnblogs.com)

WPF中TreeView控件数据绑定和后台动态添加数据(一)的更多相关文章

  1. WPF中TreeView控件数据绑定和后台动态添加数据(二)

    写在前面:在(一)中,介绍了TreeView控件MVVM模式下数据绑定的方法.在这篇文章中,将总结给节点添加事件的方法,这样说有些不对,总之实现的效果就是点击某个节点,将出现对应于该节点的页面或者数据 ...

  2. WPF中TreeView控件SelectedItemChanged方法的MVVM绑定

    问题描述:左侧treeview控件中点击不同类别的节点时,右侧的页面会显示不同的权限.比如对于My Publications,拥有Modify和Delete两种权限,对于My Subscription ...

  3. WPF中TreeView控件的使用案例

    WPF总体来说还是比较方便的,其中变化最大的主要是Listview和Treeview控件,而且TreeView似乎在WPF是一个备受指责的控件,很多人说他不好用.我这个demo主要是在wpf中使用Tr ...

  4. WPF中PasswordBox控件的Password属性的数据绑定

    原文:WPF中PasswordBox控件的Password属性的数据绑定 英文原文:http://www.wpftutorial.net/PasswordBox.html 中文原文:http://bl ...

  5. WPF中Image控件的Source属性

    原文:WPF中Image控件的Source属性 imgBook 是一个Image控件,在后台代码中我想给它指定Source的属性.我先如下方式进行: Uri uri = new Uri(strImag ...

  6. 示例:WPF中Slider控件封装的缓冲播放进度条控件

    原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...

  7. WPF中Ribbon控件的使用

    这篇博客将分享如何在WPF程序中使用Ribbon控件.Ribbon可以很大的提高软件的便捷性. 上面截图使Outlook 2010的界面,在Home标签页中,将所属的Menu都平铺的布局,非常容易的可 ...

  8. WPF中查找控件的扩展类

    在wpf中查找控件要用到VisualTreeHelper类,但这个类并没有按照名字查找控件的方法,于是搜索网络,整理出下面这个类,感觉用起来很是方便. 贴出来,供大家参考. /// <summa ...

  9. WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书

    原文:WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书 最近项目中使用弹出控件Popup,发现弹出框的对齐方式在不同的系统中存在不同(Popup在win10上是 ...

随机推荐

  1. JVM专题1: 类和类加载机制

    合集目录 JVM专题1: 类和类加载机制 Java对象的结构 在HotSpot虚拟机中, 对象在内存中存储的布局可以分为3块区域 对象头Header 实例数据Instance Data 对齐填充Pad ...

  2. Hbase 项目

     需求分析 1) 微博内容的浏览,数据库表设计 2) 用户社交体现:关注用户,取关用户 3) 拉取关注的人的微博内容 表结构 代码实现 1) 创建命名空间以及表名的定义 2) 创建微博内容表 3) 创 ...

  3. 马哈鱼间接数据流中的where-group-by子句

    马哈鱼间接数据流中的where-group-by子句 本文介绍间接数据流中的where-group-by子句. 1.列在where子句中 WHERE子句中源表中的某些列不影响目标列,但对所选行集至关重 ...

  4. 带你读AI论文:NDSS2020 UNICORN: Runtime Provenance-Based Detector

    摘要:这篇文章将详细介绍NDSS2020的<UNICORN: Runtime Provenance-Based Detector for Advanced Persistent Threats& ...

  5. TCP连接的状态转换图深度剖析

    转载请注明来源:https://www.cnblogs.com/hookjc/ 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接,如图1所示. (1)第一次握手:建立连接时 ...

  6. SpringMVC主要组件

    1.DispatcherServlet:前端控制器,接收所有请求(如果配置/,则不包含jsp) 2.handlermapping:判断请求格式,判断希望具体要执行的那个方法 3.HanderAdapt ...

  7. 你还不懂java的日志系统吗

    一.背景 在java的开发中,使用最多也绕不过去的一个话题就是日志,在程序中除了业务代码外,使用最多的就是打印日志.经常听到的这样一句话就是"打个日志调试下",没错在日常的开发.调 ...

  8. springCloud项目解决跨域问题

    通过 spring cloud gateway 实现, 方式一:选择在主启动类中注册 CorsWebFilter 类: /** * 1.允许cookies跨域 * 2.允许向该服务器提交请求的URI, ...

  9. [GWCTF 2019]re3 wp

    [GWCTF 2019]re3 关键点:AES MD5 动态调试 smc自解密 gdb使用 跟进main函数 发现一个典型smc异或自解密 可以用idc脚本 或者python patch 或者动态调试 ...

  10. Solution -「多校联训」光影交错

    \(\mathcal{Description}\)   Link.   一个游戏包含若干次卡牌抽取,每次以 \(p_l\) 的概率得到 \(+1\),\(p_d\) 的概率得到 \(-1\),否则得到 ...