using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Components; namespace AntDesign { public partial class Tree : AntDomComponentBase { #region Tree /// /// 节点前添加展开图标 /// [Parameter] public bool ShowExpand { get; set; } = true; /// /// 是否展示连接线 /// [Parameter] public bool ShowLine { get; set; } /// /// 是否展示 TreeNode title 前的图标 /// [Parameter] public bool ShowIcon { get; set; } /// /// 是否节点占据一行 /// [Parameter] public bool BlockNode { get; set; } /// /// 设置节点可拖拽 /// [Parameter] public bool Draggable { get; set; } private void SetClassMapper() { ClassMapper .Add("ant-tree") .If("ant-tree-show-line", () => ShowLine) .If("ant-tree-icon-hide", () => ShowIcon) .If("ant-tree-block-node", () => BlockNode) .If("draggable-tree", () => Draggable) .If("ant-tree-rtl", () => RTL); } #endregion Tree #region Node [Parameter] public RenderFragment Nodes { get; set; } [Parameter] public List> ChildNodes { get; set; } = new List>(); /// /// 添加节点 /// /// /// internal void AddNode(TreeNode treeNode) { ChildNodes.Add(treeNode); } #endregion Node #region Selected /// /// 支持点选多个节点(节点本身) /// [Parameter] public bool Multiple { get; set; } /// /// 选中的树节点 /// internal Dictionary> SelectedNodesDictionary { get; set; } = new Dictionary>(); public List SelectedTitles => SelectedNodesDictionary.Select(x => x.Value.Title).ToList(); internal void SelectedNodeAdd(TreeNode treeNode) { if (SelectedNodesDictionary.ContainsKey(treeNode.NodeId) == false) SelectedNodesDictionary.Add(treeNode.NodeId, treeNode); UpdateBindData(); } internal void SelectedNodeRemove(TreeNode treeNode) { if (SelectedNodesDictionary.ContainsKey(treeNode.NodeId) == true) SelectedNodesDictionary.Remove(treeNode.NodeId); UpdateBindData(); } public void DeselectAll() { foreach (var item in SelectedNodesDictionary.Select(x => x.Value).ToList()) { item.SetSelected(false); } } /// /// 选择的Key /// [Parameter] public string SelectedKey { get; set; } [Parameter] public EventCallback SelectedKeyChanged { get; set; } /// /// 选择的节点 /// [Parameter] public TreeNode SelectedNode { get; set; } [Parameter] public EventCallback> SelectedNodeChanged { get; set; } /// /// 选择的数据 /// [Parameter] public TItem SelectedData { get; set; } [Parameter] public EventCallback SelectedDataChanged { get; set; } /// /// 选择的Key集合 /// [Parameter] public string[] SelectedKeys { get; set; } [Parameter] public EventCallback SelectedKeysChanged { get; set; } /// /// 选择的节点集合 /// [Parameter] public TreeNode[] SelectedNodes { get; set; } /// /// 选择的数据集合 /// [Parameter] public TItem[] SelectedDatas { get; set; } /// /// 更新绑定数据 /// private void UpdateBindData() { if (SelectedNodesDictionary.Count == 0) { SelectedKey = null; SelectedNode = null; SelectedData = default(TItem); SelectedKeys = Array.Empty(); SelectedNodes = Array.Empty>(); SelectedDatas = Array.Empty(); } else { var selectedFirst = SelectedNodesDictionary.FirstOrDefault(); SelectedKey = selectedFirst.Value?.Key; SelectedNode = selectedFirst.Value; SelectedData = selectedFirst.Value.DataItem; SelectedKeys = SelectedNodesDictionary.Select(x => x.Value.Key).ToArray(); SelectedNodes = SelectedNodesDictionary.Select(x => x.Value).ToArray(); SelectedDatas = SelectedNodesDictionary.Select(x => x.Value.DataItem).ToArray(); } if (SelectedKeyChanged.HasDelegate) SelectedKeyChanged.InvokeAsync(SelectedKey); if (SelectedNodeChanged.HasDelegate) SelectedNodeChanged.InvokeAsync(SelectedNode); if (SelectedDataChanged.HasDelegate) SelectedDataChanged.InvokeAsync(SelectedData); if (SelectedKeysChanged.HasDelegate) SelectedKeysChanged.InvokeAsync(SelectedKeys); } #endregion Selected #region Checkable /// /// 节点前添加 Checkbox 复选框 /// [Parameter] public bool Checkable { get; set; } public List> CheckedNodes => GetCheckedNodes(ChildNodes); public List CheckedKeys => GetCheckedNodes(ChildNodes).Select(x => x.Key).ToList(); public List CheckedTitles => GetCheckedNodes(ChildNodes).Select(x => x.Title).ToList(); private List> GetCheckedNodes(List> childs) { List> checkeds = new List>(); foreach (var item in childs) { if (item.Checked) checkeds.Add(item); checkeds.AddRange(GetCheckedNodes(item.ChildNodes)); } return checkeds; } //取消所有选择项目 public void DecheckedAll() { foreach (var item in ChildNodes) { item.SetChecked(false); } } #endregion Checkable #region Search public string _searchValue; /// /// 按需筛选树,双向绑定 /// [Parameter] public string SearchValue { get => _searchValue; set { if (_searchValue == value) return; _searchValue = value; if (string.IsNullOrEmpty(value)) return; foreach (var item in ChildNodes) { SearchNode(item); } } } /// /// 返回一个值是否是页节点 /// [Parameter] public Func, bool> SearchExpression { get; set; } /// /// 查询节点 /// /// /// private bool SearchNode(TreeNode treeNode) { if (SearchExpression != null) treeNode.Matched = SearchExpression(treeNode); else treeNode.Matched = treeNode.Title.Contains(SearchValue); var hasChildMatched = treeNode.Matched; foreach (var item in treeNode.ChildNodes) { var itemMatched = SearchNode(item); hasChildMatched = hasChildMatched || itemMatched; } treeNode.HasChildMatched = hasChildMatched; return hasChildMatched; } #endregion Search #region DataBind [Parameter] public IList DataSource { get; set; } /// /// 指定一个方法,该表达式返回节点的文本。 /// [Parameter] public Func, string> TitleExpression { get; set; } /// /// 指定一个返回节点名称的方法。 /// [Parameter] public Func, string> KeyExpression { get; set; } /// /// 指定一个返回节点名称的方法。 /// [Parameter] public Func, string> IconExpression { get; set; } /// /// 返回一个值是否是页节点 /// [Parameter] public Func, bool> IsLeafExpression { get; set; } /// /// 返回子节点的方法 /// [Parameter] public Func, IList> ChildrenExpression { get; set; } #endregion DataBind #region Event /// /// 延迟加载 /// /// 必须使用async,且返回类型为Task,否则可能会出现载入时差导致显示问题 [Parameter] public EventCallback> OnNodeLoadDelayAsync { get; set; } /// /// 点击树节点触发 /// [Parameter] public EventCallback> OnClick { get; set; } /// /// 双击树节点触发 /// [Parameter] public EventCallback> OnDblClick { get; set; } /// /// 右键树节点触发 /// [Parameter] public EventCallback> OnContextMenu { get; set; } /// /// 点击树节点 Checkbox 触发 /// [Parameter] public EventCallback> OnCheckBoxChanged { get; set; } /// /// 点击展开树节点图标触发 /// [Parameter] public EventCallback> OnExpandChanged { get; set; } /// /// 搜索节点时调用(与SearchValue配合使用) /// [Parameter] public EventCallback> OnSearchValueChanged { get; set; } ///// ///// 开始拖拽时调用 ///// //public EventCallback OnDragStart { get; set; } ///// ///// dragenter 触发时调用 ///// //public EventCallback OnDragEnter { get; set; } ///// ///// dragover 触发时调用 ///// //public EventCallback OnDragOver { get; set; } ///// ///// dragleave 触发时调用 ///// //public EventCallback OnDragLeave { get; set; } ///// ///// drop 触发时调用 ///// //public EventCallback OnDrop { get; set; } ///// ///// dragend 触发时调用 ///// //public EventCallback OnDragEnd { get; set; } #endregion Event #region Template /// /// 缩进模板 /// [Parameter] public RenderFragment> IndentTemplate { get; set; } /// /// 标题模板 /// [Parameter] public RenderFragment> TitleTemplate { get; set; } /// /// 图标模板 /// [Parameter] public RenderFragment> TitleIconTemplate { get; set; } /// /// 切换图标模板 /// [Parameter] public RenderFragment> SwitcherIconTemplate { get; set; } #endregion Template protected override void OnInitialized() { SetClassMapper(); base.OnInitialized(); } /// /// Find Node /// /// Predicate /// Recursive Find /// public TreeNode FindFirstOrDefaultNode(Func, bool> predicate, bool recursive = true) { foreach (var child in ChildNodes) { if (predicate != null && predicate.Invoke(child)) { return child; } if (recursive) { var find = child.FindFirstOrDefaultNode(predicate, recursive); if (find != null) { return find; } } } return null; } /// /// from node expand to root /// /// Node public void ExpandToNode(TreeNode node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } var parentNode = node.ParentNode; while (parentNode != null) { parentNode.Expand(true); parentNode = parentNode.ParentNode; } } /// /// 展开全部节点 /// public void ExpandAll() { this.ChildNodes.ForEach(node => Switch(node, true)); } /// /// 折叠全部节点 /// public void CollapseAll() { this.ChildNodes.ForEach(node => Switch(node, false)); } private void Switch(TreeNode node, bool expanded) { node.Expand(expanded); node.ChildNodes.ForEach(n => Switch(n, expanded)); } } }