使用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. 7_python之路之python计算器

    7_python之路之python计算器 1.程序说明:Readme.cmd 1.程序文件及说明: calculator.py 2.python版本:python-3.5.3 3.程序使用:pytho ...

  2. oracle执行sql文件

    oracle执行sql文件 在PL/SQL中直接用command window执行就可以了: PL/SQL developer----->File------>New---->com ...

  3. 11 MySQL--Navicat与pymysql模块

    1.Navicat的安装下载 一.Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时, 可以使用可视化工具Navicat,以图形界面的形式操作My ...

  4. UVALive-7297-Hounded by Indecision

    OK, maybe stealing the Duchess’s favorite ruby necklace was not such a good idea. You were makingyou ...

  5. Python运维开发基础08-文件基础

    一,文件的其他打开模式 "+"表示可以同时读写某个文件: r+,可读写文件(可读:可写:可追加) w+,写读(不常用) a+,同a(不常用 "U"表示在读取时, ...

  6. 【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】

    题意 有M篇标准作文组成了一个作文库(每篇作文都是一个01的字符串),然后给出N篇作文(自然也是01字符串).如果一个长度不小于L的串在作文库中出现过,那么它是熟悉的.对于某一篇作文,我们要把它分为若 ...

  7. 6-查看centos中的用户和用户组

    转载自:http://www.cnblogs.com/ermao0423/p/9510636.html 查看centos中的用户和用户组 1.用户列表文件:/etc/passwd/ 2.用户组列表文件 ...

  8. C语言命令行处理

    一.简介 getopt()函数是一个标准库调用,可允许您使用直接的 while/switch 语句方便地逐个处理命令行参数和检测选项(带或不带附加的参数).与其类似的getopt_long()允许在几 ...

  9. labview使用场景

    测试测量:LABVIEW [6]  最初就是为测试测量而设计的,因而测试测量也就是现在LABVIEW最广泛的应用领域.经过多年的发展,LABVIEW在测试测量领域获得了广泛的承认.至今,大多数主流的测 ...

  10. [Groovy]SoapUI怎样在Groovy脚本中读取变量的值

    def saveFilePath = context.expand( '${#Project#saveFilePath}' ) def myOutFile = saveFilePath+"t ...