WPF 组织机构下拉树多选,递归绑定方式现实
使用HierarchicalDataTemplate递归绑定现实
XAML代码:
<UserControl x:Class="SunCreate.CombatPlatform.Client.MultiSelOrgTree"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="clr-namespace:SunCreate.CombatPlatform.Client"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="200">
<Grid>
<Button x:Name="btnSelected" Click="BtnClick" Height="25">
<Button.Template>
<ControlTemplate>
<Border Height="{TemplateBinding Property=Height}">
<Border.Background>
<ImageBrush ImageSource="/SunCreate.CombatPlatform.Client.Resources;component/Image/Face/Enter.png"/>
</Border.Background>
<TextBlock Margin="3 0 0 0" Text="{TemplateBinding Property=Tag}" Foreground="#1ba4f6" VerticalAlignment="Center"></TextBlock>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
<Popup x:Name="popup" StaysOpen="False" PopupAnimation="Scroll" Width="280" Height="300" AllowsTransparency="True">
<Border Background="#00234E" BorderThickness="1" BorderBrush="#224066">
<TreeView x:Name="orgTree" >
<TreeView.Template>
<ControlTemplate>
<ScrollViewer HorizontalScrollBarVisibility="Auto" MinHeight="{Binding ElementName=orgTree,Path=ActualHeight}" MinWidth="{Binding ElementName=orgTree, Path=ActualWidth}">
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</ControlTemplate>
</TreeView.Template>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type ui:MultiSelOrgTreeItemModel}" ItemsSource="{Binding Path=Nodes}" >
<Border Height="25" Width="200">
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="15"></ColumnDefinition>
<ColumnDefinition ></ColumnDefinition>
</Grid.ColumnDefinitions>
<CheckBox Visibility="{Binding Path=CheckVisiable}" Tag="{Binding}" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" Click="cxb_Node_Click" Checked="cxb_Node_Checked" Unchecked="cxb_Node_UnChecked"></CheckBox>
<Image Grid.Column="1" Width="10" Height="10" Source="/SunCreate.CombatPlatform.Client.Resources;component/Image/orgIcon.png"></Image>
<TextBlock Grid.Column="2" FontSize="12" VerticalAlignment="Center" Margin="10,0,0,0" x:Name="Name" Foreground="White" Text="{Binding Path=Name}"></TextBlock>
</Grid>
</Border>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Border>
</Popup>
</Grid>
</UserControl>
后台代码:
using SunCreate.pahf.Domain;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace SunCreate.CombatPlatform.Client
{
/// <summary>
/// 组织机构树多选
/// </summary>
public partial class MultiSelOrgTree : UserControl
{
private bool _firstLoad = true;
private log4net.ILog _log = log4net.LogManager.GetLogger(typeof(MultiSelOrgTree));
private ObservableCollection<MultiSelOrgTreeItemModel> _collection = new ObservableCollection<MultiSelOrgTreeItemModel>();
private ObservableCollection<PT_ORG_INFO> _selectedOrgs = new ObservableCollection<PT_ORG_INFO>();
private bool _inited = false; public IList<PT_ORG_INFO> SelectedOrgs
{
get { return _selectedOrgs; }
} public MultiSelOrgTree()
{
InitializeComponent(); this.Loaded += MultiSelOrgTree_Loaded;
this.orgTree.Loaded += orgTree_Loaded;
} private void MultiSelOrgTree_Loaded(object sender, RoutedEventArgs e)
{
if (_firstLoad)
{
_firstLoad = false;
InitData();
}
} private void InitData()
{
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
var list = SP.Get<Cache.ICacheService>().OrgCache.GetCameraOrgs();
var info = list.FirstOrDefault(p => p.PAR_ID == );
MultiSelOrgTreeItemModel root = new MultiSelOrgTreeItemModel();
root.Info = info;
root.Name = info.ORG_NAME;
BuildTree(root, list);
_collection.Add(root);
Dispatcher.BeginInvoke(new Action(() =>
{
this.orgTree.ItemsSource = root.Nodes;
_inited = true;
}));
});
} private void orgTree_Loaded(object sender, RoutedEventArgs e)
{
ExpandInternal(this.orgTree);
} private void BuildTree(MultiSelOrgTreeItemModel root, IList<PT_ORG_INFO> orgs)
{
var children = orgs.Where(p => p.PAR_ID == root.Info.ID);
if (children != null && children.Count() > )
{
foreach (var item in children)
{
MultiSelOrgTreeItemModel model = new MultiSelOrgTreeItemModel();
model.Info = item;
model.Name = item.ORG_NAME;
model.IsChecked = false;
model.Parent = root;
BuildTree(model, orgs);
root.Nodes.Add(model);
}
}
else
{
root.IsLeaf = true;
}
} /// <summary>
/// 展开树节点
/// </summary>
/// <param name="targetItemContainer"></param>
private void ExpandInternal(System.Windows.Controls.ItemsControl targetItemContainer)
{
try
{
if (targetItemContainer == null) return;
if (targetItemContainer.Items == null) return;
foreach (Object item in targetItemContainer.Items)
{
System.Windows.Controls.TreeViewItem treeItem = targetItemContainer.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
var info = item as TreeNode;
if (treeItem == null || !treeItem.HasItems)
{
continue;
}
//if (info.Info == null)
//{
// treeItem.Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#2ad7fa"));
//}
treeItem.IsExpanded = true;
//ExpandInternal(treeItem as ItemsControl);
}
}
catch (Exception ex)
{
_log.ErrorFormat("ExpandInternal error", ex);
}
} private void cxb_Node_UnChecked(object sender, RoutedEventArgs e) { } private void cxb_Node_Checked(object sender, RoutedEventArgs e) { } private void cxb_Node_Click(object sender, RoutedEventArgs e)
{
try
{
CheckBox cbx = sender as CheckBox;
var node = (sender as CheckBox).Tag as MultiSelOrgTreeItemModel;
if (node != null && cbx.IsChecked != null)
{
if (cbx.IsChecked.Value)
{
if (!_selectedOrgs.Contains(node.Info))
{
_selectedOrgs.Add(node.Info);
CheckChild(node, true);
}
}
else
{
if (_selectedOrgs.Contains(node.Info))
{
_selectedOrgs.Remove(node.Info);
CheckChild(node, false);
}
}
CheckParent(node);
btnSelected.Tag = string.Join(",", _selectedOrgs.ToList().ConvertAll(a => a.ORG_NAME));
}
}
catch (Exception ex)
{ }
} private void CheckParent(MultiSelOrgTreeItemModel node)
{
if (node.Parent != null)
{
bool isCheck = true;
foreach (MultiSelOrgTreeItemModel item in node.Parent.Nodes)
{
if (!item.IsChecked)
{
isCheck = false;
}
}
if (isCheck)
{
node.Parent.IsChecked = true;
if (!_selectedOrgs.Contains(node.Parent.Info))
{
_selectedOrgs.Insert(, node.Parent.Info);
}
}
else
{
node.Parent.IsChecked = false;
if (_selectedOrgs.Contains(node.Parent.Info))
{
_selectedOrgs.Remove(node.Parent.Info);
}
}
btnSelected.Tag = string.Join(",", _selectedOrgs.ToList().ConvertAll(a => a.ORG_NAME));
if (node.Parent.Parent != null)
{
CheckParent(node.Parent);
}
}
} private void CheckChild(MultiSelOrgTreeItemModel node, bool isCheck)
{
if (node.Nodes.Count > )
{
if (isCheck)
{
foreach (MultiSelOrgTreeItemModel item in node.Nodes)
{
item.IsChecked = true;
if (!_selectedOrgs.Contains(item.Info))
{
_selectedOrgs.Add(item.Info);
}
CheckChild(item, true);
}
}
else
{
foreach (MultiSelOrgTreeItemModel item in node.Nodes)
{
item.IsChecked = false;
if (_selectedOrgs.Contains(item.Info))
{
_selectedOrgs.Remove(item.Info);
}
CheckChild(item, false);
}
}
}
} private void BtnClick(object sender, RoutedEventArgs e)
{
popup.PlacementTarget = sender as Button;
popup.Placement = PlacementMode.Bottom;
popup.IsOpen = true;
} public void Select(List<string> orgIdList, ObservableCollection<MultiSelOrgTreeItemModel> Nodes = null)
{
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
while (!_inited)
{
System.Threading.Thread.Sleep();
}
this.Dispatcher.BeginInvoke(new Action(() =>
{
if (Nodes == null)
{
foreach (MultiSelOrgTreeItemModel item in _collection[].Nodes)
{
if (orgIdList.Exists(a => a == item.Info.ID.ToString()))
{
item.IsChecked = true;
if (!_selectedOrgs.Contains(item.Info))
{
_selectedOrgs.Add(item.Info);
}
}
else
{
item.IsChecked = false;
if (_selectedOrgs.Contains(item.Info))
{
_selectedOrgs.Remove(item.Info);
}
}
Select(orgIdList, item.Nodes);
}
}
else
{
foreach (MultiSelOrgTreeItemModel item in Nodes)
{
if (orgIdList.Exists(a => a == item.Info.ID.ToString()))
{
item.IsChecked = true;
if (!_selectedOrgs.Contains(item.Info))
{
_selectedOrgs.Add(item.Info);
}
}
else
{
item.IsChecked = false;
if (_selectedOrgs.Contains(item.Info))
{
_selectedOrgs.Remove(item.Info);
}
}
Select(orgIdList, item.Nodes);
}
}
btnSelected.Tag = string.Join(",", _selectedOrgs.ToList().ConvertAll(a => a.ORG_NAME));
}));
});
}
} public class MultiSelOrgTreeItemModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged; public MultiSelOrgTreeItemModel()
{
_nodes = new ObservableCollection<MultiSelOrgTreeItemModel>();
_parent = null;
} private ObservableCollection<MultiSelOrgTreeItemModel> _nodes;
public ObservableCollection<MultiSelOrgTreeItemModel> Nodes
{
get { return _nodes; }
set
{
this._nodes = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Nodes"));
}
}
} private MultiSelOrgTreeItemModel _parent;
public MultiSelOrgTreeItemModel Parent
{
get { return _parent; }
set
{
this._parent = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Parent"));
}
}
} /// <summary>
/// 名称
/// </summary>
public string _name;
public string Name
{
get { return _name; }
set
{
this._name = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
} /// <summary>
/// 是否是叶子
/// </summary>
public bool _isLeaf;
public bool IsLeaf
{
get { return _isLeaf; }
set
{
this._isLeaf = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IsLeaf"));
}
if (value)
{
CheckVisiable = Visibility.Visible;
}
}
} /// <summary>
/// 选择框是否可见
/// </summary>
public Visibility _checkVisiable = Visibility.Visible;
public Visibility CheckVisiable
{
get { return _checkVisiable; }
set
{
this._checkVisiable = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("CheckVisiable"));
}
}
} /// <summary>
/// 是否选中
/// </summary>
public bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set
{
this._isChecked = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
}
}
} public PT_ORG_INFO Info;
}
}
效果图:

WPF 组织机构下拉树多选,递归绑定方式现实的更多相关文章
- layui扩展组件,下拉树多选
项目介绍 项目中需要用到下拉树多选功能,找到两个相关组件moretop-layui-select-ext和wujiawei0926-treeselect,但是moretop-layui-selec ...
- vue 模拟下拉树
// 使用vue 做表格部分其他部分暂不修改 var app = new Vue({ el: "#freightTbl", watch: { //监听表格数据的变化[使用 watc ...
- vue-Treeselect实现组织机构(员工)下拉树的功能
知识点:前端使用vuetree的组件库,调用后台查询组织机构,包括人员的接口 实现下拉树的功能 查考: vue-treeselect官网:https://vue-treeselect.js.org/ ...
- vue+element下拉树选择器
项目需求:输入框点击弹出树形下拉结构,可多选或者单选. 解决方案:1.使用layui formSelect多选插件 2.基于vue+elementui 下拉框和树形控件组合成树形下拉结构 <el ...
- EasyUI-combotree 下拉树 数据回显时默认选中
组合树(combotree)把选择控件和下拉树结合起来.它与组合框(combobox)相似,不同的是把列表替换成树组件.组合树(combotree)支持带有用于多选的树状态复选框的树. 依赖 comb ...
- elementUI下拉树组件封装
使用组件:Popover 弹出框.Tree 树形控件 和 input 输入框 用法: 1.新建一个.vue文件,粘贴以下组件封装的代码(完全可以使用) 2.在页面需要使用下拉树的地方调用即可. (1) ...
- jquery实现下拉框多选
一.说明 本文是利用EasyUI实现下拉框多选功能,在ComboxTree其原有的基础上对样式进行了改进,样式表已上传demo,代码如下 二.代码 <!DOCTYPE html PUBLIC & ...
- zTree开发下拉树
最近,因为工作需要一个树形下拉框的组件,经过查资料一般有两种的实现方法.其一,就是使用zTree实现:其二,就是使用easyUI实现.因为公司的前端不是使用easyUI设计的,故这里我选择了zTree ...
- combobox中动态加入几个checkbox,实现下拉框多选
combobox中动态加入几个checkbox,实现下拉框多选,将一个checkbox选中时其内容就会在combobox中显示出来,将另一个checkbox选中时其内容会跟在第一个checkbox的内 ...
随机推荐
- javascript中数组的强大用法·
1 归并 var a = [{name: 'tom'},{name: 'aiscy'},{name: 'judy'},{name: 'mike'}];a.reduce(function(prev, i ...
- c++类对象 指针区别
class Test{ public: int a; Test(){ a = ; } }; int main1() { Test* t1 = new Test(); t1->a = ; Test ...
- SourceTree安装和使用
SourceTree 安装 需要注意的是在指定路径下添加一个json文件.就可以跳过身份验证,直接运行软件. SourceTree 的SSH配置 软件启动后,如果需要和远程的Gitlab仓库进行交互, ...
- MS SQL 流程控制语句
Declare myCursor cursor For Select * from table1 open myCursor Fet ...
- 新手C#string类常用函数的学习2018.08.04
ToLower()用于将字符串变为小写,注意字符串的不可变特性,需要重新赋值给另一个字符串变量. s = s.ToLower();//字符串具有不可变性,转换后需要重新赋值,不可仅有s.ToLower ...
- Solr Dismax查询解析器-深入分析
Solr 支持多种查询解析,给搜索引擎开发人员提供灵活的查询解析.Solr 中主要包含这几个查询解析器:标准查询解析器.DisMax 查询解析器,扩展 DisMax 查询解析器(eDisMax) Di ...
- IDEA00 IDEA知识点汇总
一.从头搭建IDEA开发环境 https://mp.weixin.qq.com/s/6jXHzkU8JfubhDsQJbwl8Q 1 下载最新版IDEA 1.1 官网下载安装 1.2 专业版激活 2 ...
- gradle 构建测试
以后决不能再犯此类低级错误
- zabbix监控阅读目录
一.zabbix安装 点击查看:http://www.cnblogs.com/hwlong/p/5820321.html 二.解决乱码问题 点击查看:http://www.cnblogs.com/hw ...
- 如果应用程序正在通过 <identity impersonate="true"/> 模拟,则标识将为匿名用户(通常为 IUSR_MACHINENAME)或经过身份验证的请求用户。
在配置文件中添加 <identity impersonate= "true " userName= "Administrator " pass ...