使用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 组织机构下拉树多选,递归绑定方式现实的更多相关文章

  1. layui扩展组件,下拉树多选

      项目介绍 项目中需要用到下拉树多选功能,找到两个相关组件moretop-layui-select-ext和wujiawei0926-treeselect,但是moretop-layui-selec ...

  2. vue 模拟下拉树

    // 使用vue 做表格部分其他部分暂不修改 var app = new Vue({ el: "#freightTbl", watch: { //监听表格数据的变化[使用 watc ...

  3. vue-Treeselect实现组织机构(员工)下拉树的功能

    知识点:前端使用vuetree的组件库,调用后台查询组织机构,包括人员的接口 实现下拉树的功能 查考: vue-treeselect官网:https://vue-treeselect.js.org/ ...

  4. vue+element下拉树选择器

    项目需求:输入框点击弹出树形下拉结构,可多选或者单选. 解决方案:1.使用layui formSelect多选插件 2.基于vue+elementui 下拉框和树形控件组合成树形下拉结构 <el ...

  5. EasyUI-combotree 下拉树 数据回显时默认选中

    组合树(combotree)把选择控件和下拉树结合起来.它与组合框(combobox)相似,不同的是把列表替换成树组件.组合树(combotree)支持带有用于多选的树状态复选框的树. 依赖 comb ...

  6. elementUI下拉树组件封装

    使用组件:Popover 弹出框.Tree 树形控件 和 input 输入框 用法: 1.新建一个.vue文件,粘贴以下组件封装的代码(完全可以使用) 2.在页面需要使用下拉树的地方调用即可. (1) ...

  7. jquery实现下拉框多选

    一.说明 本文是利用EasyUI实现下拉框多选功能,在ComboxTree其原有的基础上对样式进行了改进,样式表已上传demo,代码如下 二.代码 <!DOCTYPE html PUBLIC & ...

  8. zTree开发下拉树

    最近,因为工作需要一个树形下拉框的组件,经过查资料一般有两种的实现方法.其一,就是使用zTree实现:其二,就是使用easyUI实现.因为公司的前端不是使用easyUI设计的,故这里我选择了zTree ...

  9. combobox中动态加入几个checkbox,实现下拉框多选

    combobox中动态加入几个checkbox,实现下拉框多选,将一个checkbox选中时其内容就会在combobox中显示出来,将另一个checkbox选中时其内容会跟在第一个checkbox的内 ...

随机推荐

  1. pandas read_csv读取大文件的Memory error问题

    今天在读取一个超大csv文件的时候,遇到困难:首先使用office打不开然后在python中使用基本的pandas.read_csv打开文件时:MemoryError 最后查阅read_csv文档发现 ...

  2. maven settings.xml 文件

    指定jdk 的版本: <profile> <id>jdk-1.8</id> <activation> <activeByDefault>tr ...

  3. c# 二维码支持中文

    /// <summary> /// 生成二维码,保存成图片 /// </summary> static void Generate1(string text) { Barcod ...

  4. leetcode73

    public class Solution { public void SetZeroes(int[,] matrix) { ); ); var listrow = new Dictionary< ...

  5. mybatis 需要注意的点 MyBatis 插入空值时,需要指定JdbcType (201

    转自:https://blog.csdn.net/snakemoving/article/details/76052875 前天遇到一个问题 异常显示如下: 引用 Exception in threa ...

  6. 用WINSOCK API实现同步非阻塞方式的网络通讯

    Option Base 0Option Explicit '* ************************************************** *'*  模块名称:Winsock ...

  7. 【327】Python 中 PIL 实现图像缩放

    参考:Python 中使用PIL中的resize 进行缩放 参考:Python用Pillow(PIL)进行简单的图像操作(模糊.边缘增强.锐利.平滑等) 参考:廖雪峰 - Pillow 实现代码如下: ...

  8. 迷你MVVM框架 avalonjs 1.2.6发布

    avalon.mobile 针对GCC压缩器进行优化 avalon.mobile对浏览器是否支持触屏使用更好的判定 监控数组的splice,remove,removeAt进行了重构,修改直接删掉列表的 ...

  9. swagger2 注解整体说明

    @Api:用在请求的类上,表示对类的说明 tags="说明该类的作用,可以在UI界面上看到的注解" value="该参数没什么意义,在UI界面上也看到,所以不需要配置&q ...

  10. 2015年传智播客JavaEE 第168期就业班视频教程day45-ERP项目-01 05-主线流程

    采购管理 销售管理 采购退货管理  销售退货管理 老师的采购单的审核是分三级审核的,如果这个单子是个普通单子,那么审核一下就完了,如果这个单子超过100万,需要二级领导审核,如果这个单子超过500万, ...