mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-11-29 18:48:50 +08:00
refactor(module: tree): add draggable, fix default value binding (#1517)
* delete demo docs * fix tree default value and dnd * fix tree line and keys * fix switcher icon and line * fix line demo * fix switcher * add DirectoryTree demo * fix draggable demo * clean code * clean code * clean up the classmapper call * update docs * fix the docs * fix comment Co-authored-by: James Yeung <shunjiey@hotmail.com>
This commit is contained in:
parent
e98a68625a
commit
300123045f
@ -51,10 +51,10 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="ant-transfer-list-content ng-star-inserted">
|
||||
<ul class="ant-transfer-list-content">
|
||||
@foreach (var item in _leftDataSource)
|
||||
{
|
||||
<li @key="item" class="ant-transfer-list-content-item ng-star-inserted @(item.Disabled || Disabled ? DisabledClass : "")">
|
||||
<li @key="item" class="ant-transfer-list-content-item @(item.Disabled || Disabled ? DisabledClass : "")">
|
||||
<Checkbox Label="@item.Key" Checked="_sourceSelectedKeys.Contains(item.Key)" CheckedChange="@(checkedState => SelectItem(checkedState, TransferDirection.Left, item.Key))" Disabled="@(item.Disabled || Disabled)">
|
||||
@if (Render == null)
|
||||
{
|
||||
|
19
components/tree/DirectoryTree.cs
Normal file
19
components/tree/DirectoryTree.cs
Normal file
@ -0,0 +1,19 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
public class DirectoryTree<TItem> : Tree<TItem>
|
||||
{
|
||||
public DirectoryTree()
|
||||
{
|
||||
base.BlockNode = true;
|
||||
base.Directory = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
public interface IRendered<TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// 渲染完成后
|
||||
/// </summary>
|
||||
Action OnRendered { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 新节点数据,用于展开并选择新节点
|
||||
/// </summary>
|
||||
TItem NewChildData { get; set; }
|
||||
}
|
||||
}
|
@ -20,4 +20,4 @@
|
||||
</CascadingValue>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -1,45 +1,106 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
|
||||
namespace AntDesign
|
||||
{
|
||||
public partial class Tree<TItem> : AntDomComponentBase
|
||||
{
|
||||
#region fields
|
||||
|
||||
/// <summary>
|
||||
/// All of the node
|
||||
/// </summary>
|
||||
internal List<TreeNode<TItem>> _allNodes = new List<TreeNode<TItem>>();
|
||||
|
||||
/// <summary>
|
||||
/// All the checked nodes
|
||||
/// </summary>
|
||||
private ConcurrentDictionary<long, TreeNode<TItem>> _checkedNodes = new ConcurrentDictionary<long, TreeNode<TItem>>();
|
||||
|
||||
#endregion fields
|
||||
|
||||
#region Tree
|
||||
|
||||
/// <summary>
|
||||
/// 节点前添加展开图标
|
||||
/// Shows an expansion icon before the node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowExpand { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否展示连接线
|
||||
/// Shows a connecting line
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowLine { get; set; }
|
||||
public bool ShowLine
|
||||
{
|
||||
get => _showLine;
|
||||
set
|
||||
{
|
||||
_showLine = value;
|
||||
if (!_hasSetShowLeafIcon)
|
||||
{
|
||||
ShowLeafIcon = _showLine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否展示 TreeNode title 前的图标
|
||||
/// show treeNode icon icon
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowIcon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否节点占据一行
|
||||
/// Whether treeNode fill remaining horizontal space
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool BlockNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置节点可拖拽
|
||||
/// Whether the node allows drag and drop
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Draggable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The tree is disabled
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Displays the cotyledon icon
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowLeafIcon
|
||||
{
|
||||
get => _showLeafIcon;
|
||||
set
|
||||
{
|
||||
_showLeafIcon = value;
|
||||
_hasSetShowLeafIcon = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _hasSetShowLeafIcon;
|
||||
|
||||
/// <summary>
|
||||
/// Specific the Icon type of switcher
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string SwitcherIcon { get; set; }
|
||||
|
||||
public bool Directory { get; set; }
|
||||
|
||||
private void SetClassMapper()
|
||||
{
|
||||
ClassMapper
|
||||
@ -47,7 +108,9 @@ namespace AntDesign
|
||||
.If("ant-tree-show-line", () => ShowLine)
|
||||
.If("ant-tree-icon-hide", () => ShowIcon)
|
||||
.If("ant-tree-block-node", () => BlockNode)
|
||||
.If("ant-tree-directory", () => Directory)
|
||||
.If("draggable-tree", () => Draggable)
|
||||
.If("ant-tree-unselectable", () => !Selectable)
|
||||
.If("ant-tree-rtl", () => RTL);
|
||||
}
|
||||
|
||||
@ -58,16 +121,19 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public RenderFragment Nodes { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public List<TreeNode<TItem>> ChildNodes { get; set; } = new List<TreeNode<TItem>>();
|
||||
/// <summary>
|
||||
/// tree childnodes
|
||||
/// Add values when the node is initialized
|
||||
/// </summary>
|
||||
internal List<TreeNode<TItem>> ChildNodes { get; set; } = new List<TreeNode<TItem>>();
|
||||
|
||||
/// <summary>
|
||||
/// 添加节点
|
||||
/// Add a node
|
||||
/// </summary>
|
||||
/// <param name="treeNode"></param>
|
||||
/// <param name=""></param>
|
||||
internal void AddNode(TreeNode<TItem> treeNode)
|
||||
{
|
||||
treeNode.NodeIndex = ChildNodes.Count;
|
||||
ChildNodes.Add(treeNode);
|
||||
}
|
||||
|
||||
@ -76,26 +142,48 @@ namespace AntDesign
|
||||
#region Selected
|
||||
|
||||
/// <summary>
|
||||
/// 支持点选多个节点(节点本身)
|
||||
/// Whether can be selected
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Selectable { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Allows selecting multiple treeNodes
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Multiple { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string[] DefaultSelectedKeys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选中的树节点
|
||||
/// The selected tree node
|
||||
/// </summary>
|
||||
internal Dictionary<long, TreeNode<TItem>> SelectedNodesDictionary { get; set; } = new Dictionary<long, TreeNode<TItem>>();
|
||||
|
||||
public List<string> SelectedTitles => SelectedNodesDictionary.Select(x => x.Value.Title).ToList();
|
||||
internal List<string> SelectedTitles => SelectedNodesDictionary.Select(x => x.Value.Title).ToList();
|
||||
|
||||
/// <summary>
|
||||
/// Add the selected node
|
||||
/// </summary>
|
||||
/// <param name="treeNode"></param>
|
||||
internal void SelectedNodeAdd(TreeNode<TItem> treeNode)
|
||||
{
|
||||
if (SelectedNodesDictionary.ContainsKey(treeNode.NodeId) == false)
|
||||
SelectedNodesDictionary.Add(treeNode.NodeId, treeNode);
|
||||
|
||||
if (OnSelect.HasDelegate)
|
||||
{
|
||||
OnSelect.InvokeAsync(new TreeEventArgs<TItem>(this, treeNode));
|
||||
}
|
||||
|
||||
UpdateBindData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// remove the selected node
|
||||
/// </summary>
|
||||
/// <param name="treeNode"></param>
|
||||
internal void SelectedNodeRemove(TreeNode<TItem> treeNode)
|
||||
{
|
||||
if (SelectedNodesDictionary.ContainsKey(treeNode.NodeId) == true)
|
||||
@ -104,6 +192,9 @@ namespace AntDesign
|
||||
UpdateBindData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deselect all selections
|
||||
/// </summary>
|
||||
public void DeselectAll()
|
||||
{
|
||||
foreach (var item in SelectedNodesDictionary.Select(x => x.Value).ToList())
|
||||
@ -113,16 +204,19 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选择的Key
|
||||
/// @bind-SelectedKey
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string SelectedKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<string> SelectedKeyChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选择的节点
|
||||
/// @bind-SelectedNode
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public TreeNode<TItem> SelectedNode { get; set; }
|
||||
@ -131,7 +225,7 @@ namespace AntDesign
|
||||
public EventCallback<TreeNode<TItem>> SelectedNodeChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选择的数据
|
||||
/// @bing-SelectedData
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public TItem SelectedData { get; set; }
|
||||
@ -140,7 +234,7 @@ namespace AntDesign
|
||||
public EventCallback<TItem> SelectedDataChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选择的Key集合
|
||||
///
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string[] SelectedKeys { get; set; }
|
||||
@ -149,19 +243,19 @@ namespace AntDesign
|
||||
public EventCallback<string[]> SelectedKeysChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选择的节点集合
|
||||
/// The collection of selected nodes
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public TreeNode<TItem>[] SelectedNodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 选择的数据集合
|
||||
/// The selected data set
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public TItem[] SelectedDatas { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 更新绑定数据
|
||||
/// Update binding data
|
||||
/// </summary>
|
||||
private void UpdateBindData()
|
||||
{
|
||||
@ -196,28 +290,32 @@ namespace AntDesign
|
||||
#region Checkable
|
||||
|
||||
/// <summary>
|
||||
/// 节点前添加 Checkbox 复选框
|
||||
/// Add a Checkbox before the node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Checkable { get; set; }
|
||||
|
||||
public List<TreeNode<TItem>> CheckedNodes => GetCheckedNodes(ChildNodes);
|
||||
/// <summary>
|
||||
/// Check treeNode precisely; parent treeNode and children treeNodes are not associated
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool CheckStrictly { get; set; }
|
||||
|
||||
public List<string> CheckedKeys => GetCheckedNodes(ChildNodes).Select(x => x.Key).ToList();
|
||||
/// <summary>
|
||||
/// Checked keys
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string[] CheckedKeys { get; set; } = Array.Empty<string>();
|
||||
|
||||
public List<string> CheckedTitles => GetCheckedNodes(ChildNodes).Select(x => x.Title).ToList();
|
||||
|
||||
private List<TreeNode<TItem>> GetCheckedNodes(List<TreeNode<TItem>> childs)
|
||||
{
|
||||
List<TreeNode<TItem>> checkeds = new List<TreeNode<TItem>>();
|
||||
foreach (var item in childs)
|
||||
{
|
||||
if (item.Checked) checkeds.Add(item);
|
||||
checkeds.AddRange(GetCheckedNodes(item.ChildNodes));
|
||||
}
|
||||
return checkeds;
|
||||
}
|
||||
/// <summary>
|
||||
/// @bind-CheckedKeys
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<string[]> CheckedKeysChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Dechecked all selected items
|
||||
/// </summary>
|
||||
public void CheckedAll()
|
||||
{
|
||||
foreach (var item in ChildNodes)
|
||||
@ -226,7 +324,7 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
//取消所有选择项目
|
||||
// Decheck all of the checked nodes
|
||||
public void DecheckedAll()
|
||||
{
|
||||
foreach (var item in ChildNodes)
|
||||
@ -235,14 +333,41 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the keys of the default checked treeNodes
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string[] DefaultCheckedKeys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Disable node Checkbox
|
||||
/// </summary>
|
||||
public string[] DisableCheckKeys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds or removes a checkbox node
|
||||
/// </summary>
|
||||
/// <param name="treeNode"></param>
|
||||
internal void AddOrRemoveCheckNode(TreeNode<TItem> treeNode)
|
||||
{
|
||||
if (treeNode.Checked)
|
||||
_checkedNodes.TryAdd(treeNode.NodeId, treeNode);
|
||||
else
|
||||
_checkedNodes.TryRemove(treeNode.NodeId, out TreeNode<TItem> _);
|
||||
CheckedKeys = _checkedNodes.Select(x => x.Value.Key).ToArray();
|
||||
if (CheckedKeysChanged.HasDelegate) CheckedKeysChanged.InvokeAsync(CheckedKeys);
|
||||
}
|
||||
|
||||
#endregion Checkable
|
||||
|
||||
#region Search
|
||||
|
||||
public string _searchValue;
|
||||
private string _searchValue;
|
||||
private bool _showLeafIcon;
|
||||
private bool _showLine;
|
||||
|
||||
/// <summary>
|
||||
/// 按需筛选树,双向绑定
|
||||
/// search value
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string SearchValue
|
||||
@ -250,189 +375,197 @@ namespace AntDesign
|
||||
get => _searchValue;
|
||||
set
|
||||
{
|
||||
if (_searchValue == value) return;
|
||||
_searchValue = value;
|
||||
if (string.IsNullOrEmpty(value)) return;
|
||||
foreach (var item in ChildNodes)
|
||||
var allList = _allNodes.ToList();
|
||||
List<TreeNode<TItem>> searchDatas = null, exceptList = null;
|
||||
if (!String.IsNullOrEmpty(value))
|
||||
searchDatas = allList.Where(x => x.Title.Contains(value)).ToList();
|
||||
if (searchDatas != null && searchDatas.Any())
|
||||
exceptList = allList.Except(searchDatas).ToList();
|
||||
if (exceptList != null || searchDatas != null)
|
||||
{
|
||||
SearchNode(item);
|
||||
exceptList?.ForEach(m => { m.Expand(false); m.Matched = false; });
|
||||
searchDatas?.ForEach(node => { node.OpenPropagation(); node.Matched = true; });
|
||||
}
|
||||
else
|
||||
{
|
||||
allList.ForEach(m => { m.Matched = false; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
/////
|
||||
///// </summary>
|
||||
//[Parameter]
|
||||
//public EventCallback<TreeEventArgs<TItem>> OnSearchValueChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个值是否是页节点
|
||||
/// Search for matching text styles
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, bool> SearchExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询节点
|
||||
/// </summary>
|
||||
/// <param name="treeNode"></param>
|
||||
/// <returns></returns>
|
||||
private bool SearchNode(TreeNode<TItem> 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;
|
||||
}
|
||||
public string MatchedStyle { get; set; } = "";
|
||||
|
||||
#endregion Search
|
||||
|
||||
#region DataBind
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public IList<TItem> DataSource { get; set; }
|
||||
public IEnumerable<TItem> DataSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 指定一个方法,该表达式返回节点的文本。
|
||||
/// Specifies a method that returns the text of the node.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, string> TitleExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 指定一个返回节点名称的方法。
|
||||
/// Specifies a method that returns the key of the node.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, string> KeyExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 指定一个返回节点名称的方法。
|
||||
/// Specifies a method to return the node icon.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, string> IconExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回一个值是否是页节点
|
||||
/// Specifies a method that returns whether the expression is a leaf node.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, bool> IsLeafExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回子节点的方法
|
||||
/// Specifies a method to return a child node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, IList<TItem>> ChildrenExpression { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies a method to return a disabled node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, bool> DisabledExpression { get; set; }
|
||||
|
||||
#endregion DataBind
|
||||
|
||||
#region Event
|
||||
|
||||
/// <summary>
|
||||
/// 延迟加载
|
||||
/// Lazy load callbacks
|
||||
/// </summary>
|
||||
/// <remarks>必须使用async,且返回类型为Task,否则可能会出现载入时差导致显示问题</remarks>
|
||||
/// <remarks>You must use async and the return type is Task, otherwise you may experience load lag and display problems</remarks>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnNodeLoadDelayAsync { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 点击树节点触发
|
||||
/// Click the tree node callback
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 双击树节点触发
|
||||
/// Double-click the node callback
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnDblClick { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 右键树节点触发
|
||||
/// Right-click tree node callback
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnContextMenu { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 点击树节点 Checkbox 触发
|
||||
/// checked the tree node callback
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnCheckBoxChanged { get; set; }
|
||||
public EventCallback<TreeEventArgs<TItem>> OnCheck { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnSelect { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 点击展开树节点图标触发
|
||||
/// Click the expansion tree node icon to call back
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnExpandChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 搜索节点时调用(与SearchValue配合使用)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnSearchValueChanged { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// 开始拖拽时调用
|
||||
///// </summary>
|
||||
//public EventCallback<TreeEventArgs> OnDragStart { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// dragenter 触发时调用
|
||||
///// </summary>
|
||||
//public EventCallback<TreeEventArgs> OnDragEnter { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// dragover 触发时调用
|
||||
///// </summary>
|
||||
//public EventCallback<TreeEventArgs> OnDragOver { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// dragleave 触发时调用
|
||||
///// </summary>
|
||||
//public EventCallback<TreeEventArgs> OnDragLeave { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// drop 触发时调用
|
||||
///// </summary>
|
||||
//public EventCallback<TreeEventArgs> OnDrop { get; set; }
|
||||
|
||||
///// <summary>
|
||||
///// dragend 触发时调用
|
||||
///// </summary>
|
||||
//public EventCallback<TreeEventArgs> OnDragEnd { get; set; }
|
||||
|
||||
#endregion Event
|
||||
|
||||
#region Template
|
||||
|
||||
/// <summary>
|
||||
/// 缩进模板
|
||||
/// The indentation template
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<TreeNode<TItem>> IndentTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标题模板
|
||||
/// Customize the header template
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<TreeNode<TItem>> TitleTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 图标模板
|
||||
/// Customize the icon templates
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<TreeNode<TItem>> TitleIconTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 切换图标模板
|
||||
/// Customize toggle icon templates
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment<TreeNode<TItem>> SwitcherIconTemplate { get; set; }
|
||||
|
||||
#endregion Template
|
||||
|
||||
#region DragDrop
|
||||
|
||||
/// <summary>
|
||||
/// 当前拖拽项
|
||||
/// </summary>
|
||||
internal TreeNode<TItem> DragItem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the drag and drop begins
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnDragStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when drag and drop into a releasable target
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnDragEnter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when drag and drop away from a releasable target
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnDragLeave { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when drag-and-drop drops succeed
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnDrop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Drag-and-drop end callback
|
||||
/// </summary>
|
||||
/// <remarks>this callback method must be set</remarks>
|
||||
[Parameter]
|
||||
public EventCallback<TreeEventArgs<TItem>> OnDragEnd { get; set; }
|
||||
|
||||
#endregion DragDrop
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
SetClassMapper();
|
||||
@ -466,26 +599,43 @@ namespace AntDesign
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// from node expand to root
|
||||
/// </summary>
|
||||
/// <param name="node">Node</param>
|
||||
public void ExpandToNode(TreeNode<TItem> node)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(node));
|
||||
}
|
||||
var parentNode = node.ParentNode;
|
||||
while (parentNode != null)
|
||||
{
|
||||
parentNode.Expand(true);
|
||||
parentNode = parentNode.ParentNode;
|
||||
}
|
||||
}
|
||||
#region Expand
|
||||
|
||||
/// <summary>
|
||||
/// 展开全部节点
|
||||
/// All tree nodes are expanded by default
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool DefaultExpandAll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The parent node is expanded by default
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool DefaultExpandParent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expand the specified tree node by default
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string[] DefaultExpandedKeys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// (Controlled) expands the specified tree node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string[] ExpandedKeys { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string[]> ExpandedKeysChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<(string[] ExpandedKeys, TreeNode<TItem> Node, bool Expanded)> OnExpand { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool AutoExpandParent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expand all nodes
|
||||
/// </summary>
|
||||
public void ExpandAll()
|
||||
{
|
||||
@ -493,17 +643,55 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 折叠全部节点
|
||||
/// Collapse all nodes
|
||||
/// </summary>
|
||||
public void CollapseAll()
|
||||
{
|
||||
this.ChildNodes.ForEach(node => Switch(node, false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节点展开关闭
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <param name="expanded"></param>
|
||||
private void Switch(TreeNode<TItem> node, bool expanded)
|
||||
{
|
||||
node.Expand(expanded);
|
||||
node.ChildNodes.ForEach(n => Switch(n, expanded));
|
||||
}
|
||||
|
||||
internal async Task OnNodeExpand(TreeNode<TItem> node, bool expanded, MouseEventArgs args)
|
||||
{
|
||||
var expandedKeys = _allNodes.Select(x => x.Key).ToArray();
|
||||
if (OnNodeLoadDelayAsync.HasDelegate && expanded == true)
|
||||
{
|
||||
node.SetLoading(true);
|
||||
await OnNodeLoadDelayAsync.InvokeAsync(new TreeEventArgs<TItem>(this, node, args));
|
||||
node.SetLoading(false);
|
||||
}
|
||||
|
||||
if (OnExpandChanged.HasDelegate)
|
||||
{
|
||||
await OnExpandChanged.InvokeAsync(new TreeEventArgs<TItem>(this, node, args));
|
||||
}
|
||||
|
||||
if (ExpandedKeysChanged.HasDelegate)
|
||||
{
|
||||
await ExpandedKeysChanged.InvokeAsync(expandedKeys);
|
||||
}
|
||||
|
||||
if (OnExpand.HasDelegate)
|
||||
{
|
||||
await OnExpand.InvokeAsync((expandedKeys, node, expanded));
|
||||
}
|
||||
|
||||
if (AutoExpandParent && expanded)
|
||||
{
|
||||
node.ParentNode?.Expand(true);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Expand
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,16 @@ namespace AntDesign
|
||||
public TreeEventArgs() { }
|
||||
public TreeEventArgs(Tree<TItem> tree) { Tree = tree; }
|
||||
public TreeEventArgs(Tree<TItem> tree, TreeNode<TItem> node) { Tree = tree; Node = node; }
|
||||
|
||||
public TreeEventArgs(Tree<TItem> tree, TreeNode<TItem> node, MouseEventArgs originalEvent) { Tree = tree; Node = node; OriginalEvent = originalEvent; }
|
||||
|
||||
public Tree<TItem> Tree { get; set; }
|
||||
public TreeNode<TItem> Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标节点
|
||||
/// </summary>
|
||||
public TreeNode<TItem> TargetNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 原生事件
|
||||
/// </summary>
|
||||
|
@ -3,7 +3,7 @@
|
||||
@typeparam TItem
|
||||
|
||||
<span class="ant-tree-indent" aria-hidden="true">
|
||||
@for (int i = 0; i < TreeLevel; i++)
|
||||
@for (int i = TreeLevel; i > 0; i--)
|
||||
{
|
||||
if (TreeComponent.IndentTemplate != null)
|
||||
{
|
||||
@ -11,7 +11,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ant-tree-indent-unit ng-star-inserted"></span>
|
||||
var node = GetParentNode(SelfNode, i);
|
||||
<span class="ant-tree-indent-unit ant-tree-indent-unit-start @(node.IsLastNode?"ant-tree-indent-unit-end":"")"></span>
|
||||
}
|
||||
}
|
||||
</span>
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AntDesign
|
||||
@ -8,18 +9,34 @@ namespace AntDesign
|
||||
public partial class TreeIndent<TItem> : ComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 树控件本身
|
||||
/// Root Tree
|
||||
/// </summary>
|
||||
[CascadingParameter(Name = "Tree")]
|
||||
public Tree<TItem> TreeComponent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前节点
|
||||
/// Current Node
|
||||
/// </summary>
|
||||
[CascadingParameter(Name = "SelfNode")]
|
||||
public TreeNode<TItem> SelfNode { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public int TreeLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// To find specific level parent node
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <param name="level"></param>
|
||||
/// <returns></returns>
|
||||
private static TreeNode<TItem> GetParentNode(TreeNode<TItem> node, int level)
|
||||
{
|
||||
if (level > 0 && node.ParentNode != null)
|
||||
{
|
||||
return GetParentNode(node.ParentNode, level - 1);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,4 +35,4 @@
|
||||
{
|
||||
@Nodes
|
||||
}
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
|
@ -1,4 +1,8 @@
|
||||
using System;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@ -25,26 +29,40 @@ namespace AntDesign
|
||||
public TreeNode<TItem> ParentNode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 子节点
|
||||
///
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public RenderFragment Nodes { get; set; }
|
||||
|
||||
public List<TreeNode<TItem>> ChildNodes { get; set; } = new List<TreeNode<TItem>>();
|
||||
|
||||
public bool HasChildNodes => ChildNodes?.Count > 0;
|
||||
internal List<TreeNode<TItem>> ChildNodes { get; set; } = new List<TreeNode<TItem>>();
|
||||
|
||||
/// <summary>
|
||||
/// 当前节点级别
|
||||
/// Whether child nodes exist
|
||||
/// </summary>
|
||||
public int TreeLevel => (ParentNode?.TreeLevel ?? -1) + 1;//因为第一层是0,所以默认是-1
|
||||
internal bool HasChildNodes => ChildNodes?.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// 添加节点
|
||||
/// Current Node Level
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
public int TreeLevel => (ParentNode?.TreeLevel ?? -1) + 1;
|
||||
|
||||
/// <summary>
|
||||
/// record the index in children nodes list of parent node.
|
||||
/// </summary>
|
||||
internal int NodeIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determine if it is the last node in the same level nodes.
|
||||
/// </summary>
|
||||
internal bool IsLastNode => NodeIndex == (ParentNode?.ChildNodes.Count ?? TreeComponent?.ChildNodes.Count) - 1;
|
||||
|
||||
/// <summary>
|
||||
/// add node to parent node
|
||||
/// </summary>
|
||||
/// <param name="treeNode"></param>
|
||||
internal void AddNode(TreeNode<TItem> treeNode)
|
||||
{
|
||||
treeNode.NodeIndex = ChildNodes.Count;
|
||||
ChildNodes.Add(treeNode);
|
||||
IsLeaf = false;
|
||||
}
|
||||
@ -76,7 +94,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获得上级数据集合
|
||||
/// Obtain the parent data set
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<TreeNode<TItem>> GetParentNodes()
|
||||
@ -119,7 +137,7 @@ namespace AntDesign
|
||||
private string _key;
|
||||
|
||||
/// <summary>
|
||||
/// 指定当前节点的唯一标识符名称。
|
||||
/// Specifies the unique identifier name of the current node。
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Key
|
||||
@ -140,19 +158,19 @@ namespace AntDesign
|
||||
private bool _disabled;
|
||||
|
||||
/// <summary>
|
||||
/// 是否禁用
|
||||
/// The disabled state is subject to the parent node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Disabled
|
||||
{
|
||||
get { return _disabled || (ParentNode?.Disabled ?? false); }//禁用状态受制于父节点
|
||||
get { return _disabled || (ParentNode?.Disabled ?? false); }
|
||||
set { _disabled = value; }
|
||||
}
|
||||
|
||||
private bool _selected;
|
||||
|
||||
/// <summary>
|
||||
/// 是否已选中
|
||||
/// Selected or not
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Selected
|
||||
@ -165,10 +183,19 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting Selection State
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetSelected(bool value)
|
||||
{
|
||||
if (Disabled) return;
|
||||
if (!TreeComponent.Selectable && TreeComponent.Checkable)
|
||||
{
|
||||
SetChecked(!Checked);
|
||||
return;
|
||||
}
|
||||
if (_selected == value) return;
|
||||
if (Disabled == true) return;
|
||||
_selected = value;
|
||||
if (value == true)
|
||||
{
|
||||
@ -183,21 +210,91 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否异步加载状态(影响展开图标展示)
|
||||
/// Whether the load state is asynchronous (affects the display of the expansion icon)
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Loading { get; set; }
|
||||
|
||||
private bool _dragTarget;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to release the target
|
||||
/// </summary>
|
||||
internal bool DragTarget
|
||||
{
|
||||
get { return _dragTarget; }
|
||||
set
|
||||
{
|
||||
_dragTarget = value;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
internal bool DragTargetBottom { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the node to release the target location
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetTargetBottom(bool value = false)
|
||||
{
|
||||
if (DragTargetBottom == value) return;
|
||||
this.DragTargetBottom = value;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private bool TargetContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the drag and drop target node container
|
||||
/// </summary>
|
||||
internal void SetParentTargetContainer(bool value = false)
|
||||
{
|
||||
if (this.ParentNode == null) return;
|
||||
if (this.ParentNode.TargetContainer == value) return;
|
||||
this.ParentNode.TargetContainer = value;
|
||||
this.ParentNode.StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the children of the parent node
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private List<TreeNode<TItem>> GetParentChildNodes()
|
||||
{
|
||||
return this.ParentNode?.ChildNodes ?? TreeComponent.ChildNodes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove the current node
|
||||
/// </summary>
|
||||
public void RemoveNode()
|
||||
{
|
||||
GetParentChildNodes().Remove(this);
|
||||
}
|
||||
|
||||
private void SetTreeNodeClassMapper()
|
||||
{
|
||||
ClassMapper.Clear().Add("ant-tree-treenode")
|
||||
ClassMapper
|
||||
.Add("ant-tree-treenode")
|
||||
.If("ant-tree-treenode-disabled", () => Disabled)
|
||||
.If("ant-tree-treenode-switcher-open", () => SwitcherOpen)
|
||||
.If("ant-tree-treenode-switcher-close", () => SwitcherClose)
|
||||
.If("ant-tree-treenode-checkbox-checked", () => Checked)
|
||||
.If("ant-tree-treenode-checkbox-indeterminate", () => Indeterminate)
|
||||
.If("ant-tree-treenode-selected", () => Selected)
|
||||
.If("ant-tree-treenode-loading", () => Loading);
|
||||
.If("ant-tree-treenode-loading", () => Loading)
|
||||
.If("drop-target", () => DragTarget)
|
||||
.If("drag-over-gap-bottom", () => DragTarget && DragTargetBottom)
|
||||
.If("drag-over", () => DragTarget && !DragTargetBottom)
|
||||
.If("drop-container", () => TargetContainer)
|
||||
.If("ant-tree-treenode-leaf-last", () => IsLastNode);
|
||||
}
|
||||
|
||||
#endregion TreeNode
|
||||
@ -207,7 +304,7 @@ namespace AntDesign
|
||||
private bool _isLeaf = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否为叶子节点
|
||||
/// Whether it is a leaf node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool IsLeaf
|
||||
@ -228,121 +325,180 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否已展开
|
||||
/// Whether it has been expanded
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Expanded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 折叠节点
|
||||
/// Expand the node
|
||||
/// </summary>
|
||||
/// <param name="expanded"></param>
|
||||
public void Expand(bool expanded)
|
||||
{
|
||||
if (Expanded == expanded) return;
|
||||
Expanded = expanded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 真实的展开状态,路径上只要存在折叠,那么下面的全部折叠
|
||||
/// The real expand state, as long as there is a expaneded node on the path, then all the folds below
|
||||
/// </summary>
|
||||
internal bool RealDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(TreeComponent.SearchValue))
|
||||
{//普通模式下节点显示规则
|
||||
if (ParentNode == null) return true;//第一级节点默认显示
|
||||
if (ParentNode.Expanded == false) return false;//上级节点如果是折叠的,必定折叠
|
||||
return ParentNode.RealDisplay; //否则查找路径三的级节点显示情况
|
||||
}
|
||||
else
|
||||
{//筛选模式下不考虑节点是否展开,只要节点符合条件,或者存在符合条件的子节点是就展开显示
|
||||
return Matched || HasChildMatched;
|
||||
}
|
||||
if (ParentNode == null) return true;
|
||||
if (ParentNode.Expanded == false) return false;
|
||||
return ParentNode.RealDisplay;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Nodes switch
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private async Task OnSwitcherClick(MouseEventArgs args)
|
||||
{
|
||||
this.Expanded = !this.Expanded;
|
||||
if (TreeComponent.OnNodeLoadDelayAsync.HasDelegate && this.Expanded == true)
|
||||
{
|
||||
//自有节点被展开时才需要延迟加载
|
||||
//如果支持异步载入,那么在展开时是调用异步载入代码
|
||||
this.Loading = true;
|
||||
await TreeComponent.OnNodeLoadDelayAsync.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, this, args));
|
||||
this.Loading = false;
|
||||
}
|
||||
if (TreeComponent.OnExpandChanged.HasDelegate)
|
||||
await TreeComponent.OnExpandChanged.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, this, args));
|
||||
|
||||
await TreeComponent?.OnNodeExpand(this, this.Expanded, args);
|
||||
}
|
||||
|
||||
internal void SetLoading(bool loading)
|
||||
{
|
||||
this.Loading = loading;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// switcher is opened
|
||||
/// </summary>
|
||||
private bool SwitcherOpen => Expanded && !IsLeaf;
|
||||
|
||||
/// <summary>
|
||||
/// switcher is close
|
||||
/// </summary>
|
||||
private bool SwitcherClose => !Expanded && !IsLeaf;
|
||||
|
||||
/// <summary>
|
||||
/// expaned parents
|
||||
/// </summary>
|
||||
internal void OpenPropagation()
|
||||
{
|
||||
this.Expand(true);
|
||||
if (this.ParentNode != null)
|
||||
this.ParentNode.OpenPropagation();
|
||||
}
|
||||
|
||||
#endregion Switcher
|
||||
|
||||
#region Checkbox
|
||||
|
||||
/// <summary>
|
||||
/// According to check the
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Checked { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Indeterminate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool DisableCheckbox { get; set; }//是否可以选择不受父节点控制
|
||||
private bool _disableCheckbox;
|
||||
|
||||
/// <summary>
|
||||
/// 当点击选择框是触发
|
||||
/// Disable checkbox
|
||||
/// </summary>
|
||||
private async void OnCheckBoxClick(MouseEventArgs args)
|
||||
[Parameter]
|
||||
public bool DisableCheckbox
|
||||
{
|
||||
SetChecked(!Checked);
|
||||
if (TreeComponent.OnCheckBoxChanged.HasDelegate)
|
||||
await TreeComponent.OnCheckBoxChanged.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, this, args));
|
||||
get
|
||||
{
|
||||
return _disableCheckbox || (TreeComponent?.DisableCheckKeys?.Any(k => k == Key) ?? false);
|
||||
}
|
||||
set
|
||||
{
|
||||
_disableCheckbox = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置选中状态
|
||||
/// Triggered when the selection box is clicked
|
||||
/// </summary>
|
||||
private async void OnCheckBoxClick(MouseEventArgs args)
|
||||
{
|
||||
if (DisableCheckbox)
|
||||
return;
|
||||
SetChecked(!Checked);
|
||||
if (TreeComponent.OnCheck.HasDelegate)
|
||||
await TreeComponent.OnCheck.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, this, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the checkbox state
|
||||
/// </summary>
|
||||
/// <param name="check"></param>
|
||||
public void SetChecked(bool check)
|
||||
{
|
||||
if (Disabled) return;
|
||||
this.Checked = check;
|
||||
this.Indeterminate = false;
|
||||
if (HasChildNodes)
|
||||
if (!Disabled)
|
||||
{
|
||||
foreach (var subnode in ChildNodes)
|
||||
subnode?.SetChecked(check);
|
||||
if (TreeComponent.CheckStrictly)
|
||||
{
|
||||
this.Checked = check;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetChildChecked(this, check);
|
||||
if (ParentNode != null)
|
||||
ParentNode.UpdateCheckState();
|
||||
}
|
||||
}
|
||||
if (ParentNode != null)
|
||||
ParentNode.UpdateCheckState();
|
||||
else
|
||||
TreeComponent.AddOrRemoveCheckNode(this);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新选中状态
|
||||
/// Sets the checkbox status of child nodes
|
||||
/// </summary>
|
||||
/// <param name="subnode"></param>
|
||||
/// <param name="check"></param>
|
||||
private void SetChildChecked(TreeNode<TItem> subnode, bool check)
|
||||
{
|
||||
if (Disabled) return;
|
||||
this.Checked = DisableCheckbox ? false : check;
|
||||
this.Indeterminate = false;
|
||||
TreeComponent.AddOrRemoveCheckNode(this);
|
||||
if (subnode.HasChildNodes)
|
||||
foreach (var child in subnode.ChildNodes)
|
||||
child?.SetChildChecked(child, check);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update check status
|
||||
/// </summary>
|
||||
/// <param name="halfChecked"></param>
|
||||
public void UpdateCheckState(bool? halfChecked = null)
|
||||
private void UpdateCheckState(bool? halfChecked = null)
|
||||
{
|
||||
if (halfChecked.HasValue && halfChecked.Value == true)
|
||||
{//如果子元素存在不确定状态,父元素必定存在不确定状态
|
||||
if (halfChecked == true)
|
||||
{
|
||||
//If the child node is indeterminate, the parent node must is indeterminate.
|
||||
this.Checked = false;
|
||||
this.Indeterminate = true;
|
||||
}
|
||||
else if (HasChildNodes == true)
|
||||
{//判断当前节点的选择状态
|
||||
else if (HasChildNodes == true && !DisableCheckbox)
|
||||
{
|
||||
//Determines the selection status of the current node
|
||||
bool hasChecked = false;
|
||||
bool hasUnchecked = false;
|
||||
|
||||
foreach (var item in ChildNodes)
|
||||
{
|
||||
if (item.Indeterminate == true) break;
|
||||
if (item.Checked == true) hasChecked = true;
|
||||
if (item.Checked == false) hasUnchecked = true;
|
||||
if (!item.DisableCheckbox && !item.Disabled)
|
||||
{
|
||||
if (item.Indeterminate == true) break;
|
||||
if (item.Checked == true) hasChecked = true;
|
||||
if (item.Checked == false) hasUnchecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChecked && !hasUnchecked)
|
||||
@ -361,11 +517,11 @@ namespace AntDesign
|
||||
this.Indeterminate = true;
|
||||
}
|
||||
}
|
||||
TreeComponent.AddOrRemoveCheckNode(this);
|
||||
|
||||
if (ParentNode != null)
|
||||
ParentNode.UpdateCheckState(this.Indeterminate);
|
||||
|
||||
//当达到最顶级后进行刷新状态,避免每一级刷新的性能问题
|
||||
if (ParentNode == null)
|
||||
StateHasChanged();
|
||||
}
|
||||
@ -380,7 +536,7 @@ namespace AntDesign
|
||||
private string _icon;
|
||||
|
||||
/// <summary>
|
||||
/// 节点前的图标,与 `ShowIcon` 组合使用
|
||||
/// The icon in front of the node
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Icon
|
||||
@ -398,11 +554,17 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<TreeNode<TItem>> IconTemplate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string SwitcherIcon { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<TreeNode<TItem>> SwitcherIconTemplate { get; set; }
|
||||
|
||||
private string _title;
|
||||
|
||||
/// <summary>
|
||||
/// 文本
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Title
|
||||
{
|
||||
@ -419,6 +581,9 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment TitleTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// title是否包含SearchValue(搜索使用)
|
||||
/// </summary>
|
||||
@ -431,7 +596,7 @@ namespace AntDesign
|
||||
|
||||
#endregion Title
|
||||
|
||||
#region 数据绑定
|
||||
#region data binding
|
||||
|
||||
[Parameter]
|
||||
public TItem DataItem { get; set; }
|
||||
@ -456,15 +621,15 @@ namespace AntDesign
|
||||
if (this.ParentNode != null)
|
||||
return this.ParentNode.ChildDataItems;
|
||||
else
|
||||
return this.TreeComponent.DataSource;
|
||||
return this.TreeComponent.DataSource.ToList();
|
||||
}
|
||||
|
||||
#endregion 数据绑定
|
||||
#endregion data binding
|
||||
|
||||
#region 节点数据操作
|
||||
#region Node data operation
|
||||
|
||||
/// <summary>
|
||||
/// 添加子节点
|
||||
/// Add child node
|
||||
/// </summary>
|
||||
/// <param name="dataItem"></param>
|
||||
public void AddChildNode(TItem dataItem)
|
||||
@ -473,7 +638,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节点后面添加节点
|
||||
/// Add a node next the node
|
||||
/// </summary>
|
||||
/// <param name="dataItem"></param>
|
||||
public void AddNextNode(TItem dataItem)
|
||||
@ -486,7 +651,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 节点前面添加节点
|
||||
/// Add a node before the node
|
||||
/// </summary>
|
||||
/// <param name="dataItem"></param>
|
||||
public void AddPreviousNode(TItem dataItem)
|
||||
@ -499,7 +664,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除节点
|
||||
/// remove
|
||||
/// </summary>
|
||||
public void Remove()
|
||||
{
|
||||
@ -507,6 +672,10 @@ namespace AntDesign
|
||||
parentChildDataItems.Remove(this.DataItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The node moves into the child node
|
||||
/// </summary>
|
||||
/// <param name="treeNode">target node</param>
|
||||
public void MoveInto(TreeNode<TItem> treeNode)
|
||||
{
|
||||
if (treeNode == this || this.DataItem.Equals(treeNode.DataItem)) return;
|
||||
@ -516,7 +685,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上移节点
|
||||
/// Move up the nodes
|
||||
/// </summary>
|
||||
public void MoveUp()
|
||||
{
|
||||
@ -528,7 +697,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下移节点
|
||||
/// Move down the node
|
||||
/// </summary>
|
||||
public void MoveDown()
|
||||
{
|
||||
@ -540,7 +709,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 降级节点
|
||||
///
|
||||
/// </summary>
|
||||
public void Downgrade()
|
||||
{
|
||||
@ -552,7 +721,7 @@ namespace AntDesign
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 升级节点
|
||||
/// Upgrade nodes
|
||||
/// </summary>
|
||||
public void Upgrade()
|
||||
{
|
||||
@ -563,25 +732,6 @@ namespace AntDesign
|
||||
parentChildDataItems.Insert(index + 1, this.DataItem);
|
||||
}
|
||||
|
||||
#endregion 节点数据操作
|
||||
|
||||
protected override void OnInitialized()
|
||||
|
||||
{
|
||||
SetTreeNodeClassMapper();
|
||||
if (ParentNode != null)
|
||||
ParentNode.AddNode(this);
|
||||
else
|
||||
TreeComponent.AddNode(this);
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
SetTreeNodeClassMapper();
|
||||
base.OnParametersSet();
|
||||
}
|
||||
|
||||
private void AddNodeAndSelect(TItem dataItem)
|
||||
{
|
||||
var tn = ChildNodes.FirstOrDefault(treeNode => treeNode.DataItem.Equals(dataItem));
|
||||
@ -591,5 +741,111 @@ namespace AntDesign
|
||||
tn.SetSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drag and drop into child nodes
|
||||
/// </summary>
|
||||
/// <param name="treeNode">目标</param>
|
||||
internal void DragMoveInto(TreeNode<TItem> treeNode)
|
||||
{
|
||||
if (TreeComponent.DataSource == null || !TreeComponent.DataSource.Any())
|
||||
return;
|
||||
if (treeNode == this || this.DataItem.Equals(treeNode.DataItem)) return;
|
||||
|
||||
Remove();
|
||||
|
||||
treeNode.AddChildNode(this.DataItem);
|
||||
treeNode.IsLeaf = false;
|
||||
treeNode.Expand(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drag and drop to the bottom of the target
|
||||
/// </summary>
|
||||
/// <param name="treeNode">目标</param>
|
||||
internal void DragMoveDown(TreeNode<TItem> treeNode)
|
||||
{
|
||||
if (TreeComponent.DataSource == null || !TreeComponent.DataSource.Any())
|
||||
return;
|
||||
if (treeNode == this || this.DataItem.Equals(treeNode.DataItem)) return;
|
||||
Remove();
|
||||
treeNode.AddNextNode(this.DataItem);
|
||||
}
|
||||
|
||||
#endregion Node data operation
|
||||
|
||||
bool _defaultBinding;
|
||||
|
||||
protected override void OnInitialized()
|
||||
|
||||
{
|
||||
SetTreeNodeClassMapper();
|
||||
if (ParentNode != null)
|
||||
ParentNode.AddNode(this);
|
||||
else
|
||||
{
|
||||
TreeComponent.AddNode(this);
|
||||
if (!TreeComponent.DefaultExpandAll && TreeComponent.DefaultExpandParent)
|
||||
Expand(true);
|
||||
}
|
||||
TreeComponent._allNodes.Add(this);
|
||||
|
||||
if (TreeComponent.DisabledExpression != null)
|
||||
Disabled = TreeComponent.DisabledExpression(this);
|
||||
|
||||
if (TreeComponent.DefaultExpandAll)
|
||||
Expand(true);
|
||||
else if (TreeComponent.ExpandedKeys != null)
|
||||
{
|
||||
Expand(TreeComponent.ExpandedKeys.Any(k => k == this.Key));
|
||||
}
|
||||
|
||||
if (TreeComponent.Selectable && TreeComponent.SelectedKeys != null)
|
||||
{
|
||||
this.Selected = TreeComponent.SelectedKeys.Any(k => k == this.Key);
|
||||
}
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
DefaultBinding();
|
||||
base.OnParametersSet();
|
||||
}
|
||||
|
||||
private void DefaultBinding()
|
||||
{
|
||||
if (!_defaultBinding)
|
||||
{
|
||||
_defaultBinding = true;
|
||||
if (this.Checked)
|
||||
this.SetChecked(true);
|
||||
TreeComponent.DefaultCheckedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = TreeComponent._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.SetChecked(true);
|
||||
});
|
||||
|
||||
TreeComponent.DefaultSelectedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = TreeComponent._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.SetSelected(true);
|
||||
});
|
||||
|
||||
if (!TreeComponent.DefaultExpandAll)
|
||||
{
|
||||
if (this.Expanded)
|
||||
this.OpenPropagation();
|
||||
TreeComponent.DefaultExpandedKeys?.ForEach(k =>
|
||||
{
|
||||
var node = TreeComponent._allNodes.FirstOrDefault(x => x.Key == k);
|
||||
if (node != null)
|
||||
node.OpenPropagation();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ namespace AntDesign
|
||||
public partial class TreeNodeCheckbox<TItem> : ComponentBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 树控件本身
|
||||
/// Root Tree
|
||||
/// </summary>
|
||||
[CascadingParameter(Name = "Tree")]
|
||||
public Tree<TItem> TreeComponent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前节点
|
||||
/// Current Node
|
||||
/// </summary>
|
||||
[CascadingParameter(Name = "SelfNode")]
|
||||
public TreeNode<TItem> SelfNode { get; set; }
|
||||
@ -22,11 +22,11 @@ namespace AntDesign
|
||||
|
||||
private void SetClassMap()
|
||||
{
|
||||
ClassMapper.Clear().Add("ant-tree-checkbox")
|
||||
ClassMapper
|
||||
.Add("ant-tree-checkbox")
|
||||
.If("ant-tree-checkbox-checked", () => SelfNode.Checked)
|
||||
.If("ant-tree-checkbox-indeterminate", () => SelfNode.Indeterminate)
|
||||
.If("ant-tree-checkbox-disabled", () => SelfNode.Disabled || SelfNode.DisableCheckbox)
|
||||
;
|
||||
.If("ant-tree-checkbox-disabled", () => SelfNode.Disabled || SelfNode.DisableCheckbox);
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
@ -35,12 +35,6 @@ namespace AntDesign
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
SetClassMap();
|
||||
base.OnParametersSet();
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<MouseEventArgs> OnCheckBoxClick { get; set; }
|
||||
|
||||
|
@ -3,49 +3,66 @@
|
||||
@typeparam TItem
|
||||
|
||||
<span class="@ClassMapper.Class" @onclick="OnClick">
|
||||
@if (IsShowSwitchIcon)
|
||||
@if (SelfNode.Loading)
|
||||
{
|
||||
@if (!SelfNode.Loading)
|
||||
<Icon Type="loading" Theme="outline" Class="ant-tree-switcher-loading-icon" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<!-- node has its own switcher icon -->
|
||||
@if (SelfNode?.SwitcherIconTemplate != null || SelfNode?.SwitcherIcon != null)
|
||||
{
|
||||
if (TreeComponent.SwitcherIconTemplate != null)
|
||||
if (SelfNode.SwitcherIconTemplate != null)
|
||||
{
|
||||
@TreeComponent.SwitcherIconTemplate(SelfNode)
|
||||
<span class="ant-tree-switcher-icon">
|
||||
@SelfNode.SwitcherIconTemplate(SelfNode)
|
||||
</span>
|
||||
}
|
||||
else
|
||||
else if (SelfNode.SwitcherIcon != null)
|
||||
{
|
||||
<Icon Type="caret-down" Theme="outline" class="ant-tree-switcher-icon" />
|
||||
<Icon Type="@SelfNode.SwitcherIcon" Class="ant-tree-switcher-icon" />
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="loading" Theme="outline" class="ant-tree-switcher-loading-icon" />
|
||||
}
|
||||
|
||||
}
|
||||
@if (TreeComponent.ShowLine)
|
||||
{
|
||||
@if (!SelfNode.Loading)
|
||||
{
|
||||
if (TreeComponent.SwitcherIconTemplate != null)
|
||||
@if (TreeComponent.ShowLine)
|
||||
{
|
||||
@TreeComponent.SwitcherIconTemplate(SelfNode)
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (IsShowLineIcon)
|
||||
<!-- When the node is not leaf, then show switcher icon -->
|
||||
if (!SelfNode.IsLeaf)
|
||||
{
|
||||
<Icon Type="@(IsSwitcherOpen ? "minus-square" : "plus-square")" Theme="outline" class="ant-tree-switcher-line-icon" />
|
||||
@if (TreeComponent.SwitcherIconTemplate != null)
|
||||
{
|
||||
<span class="ant-tree-switcher-icon">
|
||||
@TreeComponent.SwitcherIconTemplate(SelfNode)
|
||||
</span>
|
||||
}
|
||||
else if (TreeComponent.SwitcherIcon != null)
|
||||
{
|
||||
<Icon Type="TreeComponent.SwitcherIcon" Class="ant-tree-switcher-icon" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="@(IsSwitcherOpen ? "minus-square" : "plus-square")" Class="ant-tree-switcher-line-icon" />
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="file" Theme="outline" class="ant-tree-switcher-line-icon" />
|
||||
<!-- Show the leaf icon (file) or leaf line (└) -->
|
||||
if (TreeComponent.ShowLeafIcon)
|
||||
{
|
||||
<Icon Type="file" Theme="outline" Class="ant-tree-switcher-line-icon" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ant-tree-switcher-leaf-line"></span>
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!SelfNode.IsLeaf)
|
||||
{
|
||||
<!-- node is not leaf and not show line, then show the default arrow icon -->
|
||||
<Icon Type="caret-down" Theme="outline" Class="ant-tree-switcher-icon" />
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="loading" Theme="outline" class="ant-tree-switcher-loading-icon" />
|
||||
}
|
||||
|
||||
}
|
||||
</span>
|
@ -22,10 +22,6 @@ namespace AntDesign
|
||||
[CascadingParameter(Name = "SelfNode")]
|
||||
public TreeNode<TItem> SelfNode { get; set; }
|
||||
|
||||
private bool IsShowLineIcon => !SelfNode.IsLeaf && TreeComponent.ShowLine;
|
||||
|
||||
private bool IsShowSwitchIcon => !SelfNode.IsLeaf && !TreeComponent.ShowLine;
|
||||
|
||||
/// <summary>
|
||||
/// 节点是否处于展开状态
|
||||
/// </summary>
|
||||
@ -40,7 +36,8 @@ namespace AntDesign
|
||||
|
||||
private void SetClassMap()
|
||||
{
|
||||
ClassMapper.Clear().Add("ant-tree-switcher")
|
||||
ClassMapper
|
||||
.Add("ant-tree-switcher")
|
||||
.If("ant-tree-switcher-noop", () => SelfNode.IsLeaf)
|
||||
.If("ant-tree-switcher_open", () => IsSwitcherOpen)
|
||||
.If("ant-tree-switcher_close", () => IsSwitcherClose);
|
||||
@ -52,12 +49,6 @@ namespace AntDesign
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
SetClassMap();
|
||||
base.OnParametersSet();
|
||||
}
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<MouseEventArgs> OnSwitcherClick { get; set; }
|
||||
|
||||
|
@ -1,36 +1,113 @@
|
||||
@namespace AntDesign
|
||||
@inherits ComponentBase
|
||||
@typeparam TItem
|
||||
|
||||
<span class="@TitleClassMapper.Class" title="@SelfNode.Title" @onclick="OnClick" @ondblclick="OnDblClick" draggable="@CanDraggable" aria-grabbed="@CanDraggable">
|
||||
@if (TreeComponent.TitleIconTemplate != null && TreeComponent.ShowIcon)
|
||||
{
|
||||
<span class="ant-tree-iconEle @(IsSwitcherOpen?"ant-tree-icon__open":"") @(IsSwitcherClose?"ant-tree-icon__close":"") @(SelfNode.Loading?"ant-tree-icon_loading":"")">
|
||||
<span class="ant-tree-iconEle ant-tree-icon__customize">
|
||||
@TreeComponent.TitleIconTemplate(SelfNode)
|
||||
@if (CanDraggable)
|
||||
{
|
||||
<span class="@TitleClassMapper.Class" title="@SelfNode.Title" @onclick="OnClick" @ondblclick="OnDblClick" draggable="true"
|
||||
@ondragover:preventDefault @ondragover="OnDragOver" @ondragleave="OnDragLeave" @ondragenter="OnDragEnter" @ondrop:preventDefault @ondrop="OnDrop"
|
||||
@ondragstart="OnDragStart" @ondragend="OnDragEnd" aria-grabbed="true">
|
||||
@if (TreeComponent.TitleIconTemplate != null && TreeComponent.ShowIcon)
|
||||
{
|
||||
<span class="ant-tree-iconEle @(IsSwitcherOpen?"ant-tree-icon__open":"") @(IsSwitcherClose?"ant-tree-icon__close":"") @(SelfNode.Loading?"ant-tree-icon_loading":"")">
|
||||
<span class="ant-tree-iconEle ant-tree-icon__customize">
|
||||
@TreeComponent.TitleIconTemplate(SelfNode)
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(SelfNode.Icon) == false && TreeComponent.ShowIcon)
|
||||
{
|
||||
<span class="ant-tree-iconEle @(IsSwitcherOpen?"ant-tree-icon__open":"") @(IsSwitcherClose?"ant-tree-icon__close":"") @(SelfNode.Loading?"ant-tree-icon_loading":"")">
|
||||
<span class="ant-tree-iconEle ant-tree-icon__customize">
|
||||
@if (string.IsNullOrWhiteSpace(SelfNode.Icon) == false)
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(SelfNode.Icon) == false && TreeComponent.ShowIcon)
|
||||
{
|
||||
<span class="ant-tree-iconEle @(IsSwitcherOpen?"ant-tree-icon__open":"") @(IsSwitcherClose?"ant-tree-icon__close":"") @(SelfNode.Loading?"ant-tree-icon_loading":"")">
|
||||
<span class="ant-tree-iconEle ant-tree-icon__customize">
|
||||
@if (string.IsNullOrWhiteSpace(SelfNode.Icon) == false)
|
||||
{
|
||||
<Icon Type="@SelfNode.Icon" Theme="outline" />
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
@if (TreeComponent.TitleTemplate != null)
|
||||
{
|
||||
@TreeComponent.TitleTemplate(SelfNode)
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ant-tree-title" style="pointer-events: none;">
|
||||
@if (SelfNode.TitleTemplate != null)
|
||||
{
|
||||
<Icon Type="@SelfNode.Icon" Theme="outline" />
|
||||
@SelfNode.TitleTemplate
|
||||
}
|
||||
else if (SelfNode.Matched)
|
||||
{
|
||||
var value = $"<span Style=\"{TreeComponent.MatchedStyle}\">{TreeComponent.SearchValue}</span>";
|
||||
<span>
|
||||
@((MarkupString)SelfNode.Title.Replace(TreeComponent.SearchValue, value))
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@SelfNode.Title
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
|
||||
@if (TreeComponent.TitleTemplate != null)
|
||||
{
|
||||
@TreeComponent.TitleTemplate(SelfNode)
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ant-tree-title">
|
||||
@SelfNode.Title
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
@if (SelfNode.DragTarget)
|
||||
{
|
||||
<div class="ant-tree-drop-indicator" style="left:@(SelfNode.DragTargetBottom?"4px":"28px");right:0;bottom:-3px;"></div>
|
||||
}
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@TitleClassMapper.Class" title="@SelfNode.Title" @onclick="OnClick" @ondblclick="OnDblClick">
|
||||
@if (TreeComponent.TitleIconTemplate != null && TreeComponent.ShowIcon)
|
||||
{
|
||||
<span class="ant-tree-iconEle @(IsSwitcherOpen?"ant-tree-icon__open":"") @(IsSwitcherClose?"ant-tree-icon__close":"") @(SelfNode.Loading?"ant-tree-icon_loading":"")">
|
||||
<span class="ant-tree-iconEle ant-tree-icon__customize">
|
||||
@TreeComponent.TitleIconTemplate(SelfNode)
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
else if ((!string.IsNullOrWhiteSpace(SelfNode.Icon) || SelfNode.IconTemplate != null) && TreeComponent.ShowIcon)
|
||||
{
|
||||
<span class="ant-tree-iconEle @(IsSwitcherOpen?"ant-tree-icon__open":"") @(IsSwitcherClose?"ant-tree-icon__close":"") @(SelfNode.Loading?"ant-tree-icon_loading":"")">
|
||||
<span class="ant-tree-iconEle ant-tree-icon__customize">
|
||||
@if (SelfNode.IconTemplate != null)
|
||||
{
|
||||
@SelfNode.IconTemplate(SelfNode)
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(SelfNode.Icon))
|
||||
{
|
||||
<Icon Type="@SelfNode.Icon" Theme="outline" />
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
@if (TreeComponent.TitleTemplate != null)
|
||||
{
|
||||
@TreeComponent.TitleTemplate(SelfNode)
|
||||
}
|
||||
else if (SelfNode.TitleTemplate != null)
|
||||
{
|
||||
@SelfNode.TitleTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="ant-tree-title">
|
||||
@if (SelfNode.Matched)
|
||||
{
|
||||
var value = $"<span Style=\"{TreeComponent.MatchedStyle}\">{TreeComponent.SearchValue}</span>";
|
||||
<span>
|
||||
@((MarkupString)SelfNode.Title.Replace(TreeComponent.SearchValue, value))
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@SelfNode.Title
|
||||
}
|
||||
</span>
|
||||
}
|
||||
@if (SelfNode.DragTarget)
|
||||
{
|
||||
<div class="ant-tree-drop-indicator" style="left:@(SelfNode.DragTargetBottom?"4px":"28px");right:0;bottom:-3px;"></div>
|
||||
}
|
||||
</span>
|
||||
}
|
@ -9,6 +9,17 @@ namespace AntDesign
|
||||
{
|
||||
public partial class TreeNodeTitle<TItem> : ComponentBase
|
||||
{
|
||||
#region fields
|
||||
|
||||
private const double OffSETX = 25;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private double _dragTargetClientX = 0;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 树控件本身
|
||||
/// </summary>
|
||||
@ -31,7 +42,8 @@ namespace AntDesign
|
||||
|
||||
private void SetTitleClassMapper()
|
||||
{
|
||||
TitleClassMapper.Clear().Add("ant-tree-node-content-wrapper")
|
||||
TitleClassMapper
|
||||
.Add("ant-tree-node-content-wrapper")
|
||||
.If("draggable", () => CanDraggable)
|
||||
.If("ant-tree-node-content-wrapper-open", () => IsSwitcherOpen)
|
||||
.If("ant-tree-node-content-wrapper-close", () => IsSwitcherClose)
|
||||
@ -44,12 +56,11 @@ namespace AntDesign
|
||||
base.OnInitialized();
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
SetTitleClassMapper();
|
||||
base.OnParametersSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private async Task OnClick(MouseEventArgs args)
|
||||
{
|
||||
SelfNode.SetSelected(!SelfNode.Selected);
|
||||
@ -59,10 +70,103 @@ namespace AntDesign
|
||||
await TreeComponent.OnContextMenu.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, SelfNode, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private async Task OnDblClick(MouseEventArgs args)
|
||||
{
|
||||
if (TreeComponent.OnDblClick.HasDelegate && args.Button == 0)
|
||||
await TreeComponent.OnDblClick.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, SelfNode, args));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
private void OnDragStart(DragEventArgs e)
|
||||
{
|
||||
TreeComponent.DragItem = SelfNode;
|
||||
SelfNode.Expand(false);
|
||||
if (TreeComponent.OnDragStart.HasDelegate)
|
||||
TreeComponent.OnDragStart.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, SelfNode));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Leaving releases the target
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
private void OnDragLeave(DragEventArgs e)
|
||||
{
|
||||
SelfNode.DragTarget = false;
|
||||
SelfNode.SetParentTargetContainer();
|
||||
if (TreeComponent.OnDragLeave.HasDelegate)
|
||||
TreeComponent.OnDragLeave.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, SelfNode));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
private void OnDragEnter(DragEventArgs e)
|
||||
{
|
||||
if (TreeComponent.DragItem == SelfNode) return;
|
||||
SelfNode.DragTarget = true;
|
||||
_dragTargetClientX = e.ClientX;
|
||||
|
||||
System.Diagnostics.Debug.WriteLine($"OnDragEnter {SelfNode.Title} {System.Text.Json.JsonSerializer.Serialize(e)}");
|
||||
|
||||
if (TreeComponent.OnDragEnter.HasDelegate)
|
||||
TreeComponent.OnDragEnter.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, SelfNode));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be treated as a child if the target is moved to the right beyond the OffsetX distance
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
private void OnDragOver(DragEventArgs e)
|
||||
{
|
||||
if (TreeComponent.DragItem == SelfNode) return;
|
||||
if (e.ClientX - _dragTargetClientX > OffSETX)
|
||||
{
|
||||
SelfNode.SetTargetBottom();
|
||||
SelfNode.SetParentTargetContainer();
|
||||
SelfNode.Expand(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SelfNode.SetTargetBottom(true);
|
||||
SelfNode.SetParentTargetContainer(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
private void OnDrop(DragEventArgs e)
|
||||
{
|
||||
SelfNode.DragTarget = false;
|
||||
SelfNode.SetParentTargetContainer();
|
||||
if (SelfNode.DragTargetBottom)
|
||||
TreeComponent.DragItem.DragMoveDown(SelfNode);
|
||||
else
|
||||
TreeComponent.DragItem.DragMoveInto(SelfNode);
|
||||
|
||||
if (TreeComponent.OnDrop.HasDelegate)
|
||||
TreeComponent.OnDrop.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, TreeComponent.DragItem) { TargetNode = SelfNode });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drag the end
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
private void OnDragEnd(DragEventArgs e)
|
||||
{
|
||||
if (TreeComponent.OnDragEnd.HasDelegate)
|
||||
TreeComponent.OnDragEnd.InvokeAsync(new TreeEventArgs<TItem>(TreeComponent, TreeComponent.DragItem) { TargetNode = SelfNode });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,8 @@
|
||||
using System;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -49,7 +53,7 @@ namespace AntDesign.Docs.Build.CLI.Command
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
Console.WriteLine(ex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,30 +1,41 @@
|
||||
|
||||
<Tree Checkable BlockNode TItem="string">
|
||||
<Tree TItem="string" Checkable
|
||||
DefaultExpandedKeys="@(new[] { "0-0-0", "0-0-1"})"
|
||||
DefaultSelectedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
||||
DefaultCheckedKeys="@(new[] {"0-0-0", "0-0-1" })"
|
||||
OnSelect="OnSelect"
|
||||
OnCheck="OnCheck">
|
||||
<Nodes>
|
||||
<TreeNode Title="A" TItem="string">
|
||||
<TreeNode Title="parent 1" Key="0-0" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1" TItem="string">
|
||||
<TreeNode Title="parent 1-0" Key="0-0-0" Disabled TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A1-2" TItem="string"></TreeNode>
|
||||
<TreeNode Title="leaf" Key="0-0-0-0" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="leaf" Key="0-0-0-1" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A2" Disabled TItem="string">
|
||||
<TreeNode Title="parent 1-1" Key="0-0-1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A2-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A2-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A3" DisableCheckbox TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A3-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-2" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-3" Disabled TItem="string"></TreeNode>
|
||||
|
||||
<TreeNode Key="0-0-1-0" TItem="string">
|
||||
<TitleTemplate>
|
||||
<span style="color: #1890ff; ">sss</span>
|
||||
</TitleTemplate>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="B" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</Tree>
|
||||
</Tree>
|
||||
|
||||
@code{
|
||||
|
||||
void OnSelect(TreeEventArgs<string> args)
|
||||
{
|
||||
Console.WriteLine("OnSelect");
|
||||
}
|
||||
|
||||
void OnCheck(TreeEventArgs<string> args)
|
||||
{
|
||||
Console.WriteLine("onCheck");
|
||||
}
|
||||
}
|
@ -1,34 +1,46 @@
|
||||
<Tree @ref="tree" Checkable Multiple TItem="string">
|
||||
<Tree @ref="_tree"
|
||||
Checkable
|
||||
TItem="string"
|
||||
@bind-ExpandedKeys="expandedKeys"
|
||||
@bind-CheckedKeys="checkedKeys"
|
||||
@bind-SelectedKeys="selectedKeys"
|
||||
OnExpand="OnExpand"
|
||||
OnSelect="OnSelect"
|
||||
OnCheck="OnCheck"
|
||||
AutoExpandParent="autoExpandParent">
|
||||
<Nodes>
|
||||
<TreeNode Title="A" Key="100" TItem="string">
|
||||
<TreeNode Title="0-0" Key="0-0" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1" Key="110" TItem="string">
|
||||
<TreeNode Title="0-0-0" Key="0-0-0" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1-1" Key="111" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A2-2" Key="112" TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-0-0-0" Key="0-0-0-0" TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-0-0-1" Key="0-0-0-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-0-0-2" Key="0-0-0-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A2" Key="120" Disabled TItem="string">
|
||||
<TreeNode Title="0-0-1" Key="0-0-1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A2-1" Key="121" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A1-2" Key="122" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A3" Key="130" DisableCheckbox TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A3-1" Key="131" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-2" Key="132" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-3" Key="133" Disabled TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-0-1-0" Key="0-0-1-0" TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-0-1-1" Key="0-0-1-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-0-1-2" Key="0-0-1-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="0-0-2" Key="0-0-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="B" Key="200" TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-1" Key="0-1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="0-1-0-0" Key="0-1-0-0" TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-1-0-1" Key="0-1-0-1" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="0-1-0-2" Key="0-1-0-2" Disabled TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="0-2" Key="0-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</Tree>
|
||||
|
||||
<br />
|
||||
<Button OnClick="PrintCheckedNodesTitle">Print Checked Nodes Title</Button>
|
||||
@*<Button OnClick="PrintCheckedNodesTitle">Print Checked Nodes Title</Button>*@
|
||||
|
||||
<Button OnClick="PrintCheckedNodesKey">Print Checked Nodes Key</Button>
|
||||
|
||||
@ -36,7 +48,7 @@
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<Button OnClick="PrintSelectedNodes">Print Selected Nodes</Button>
|
||||
@*<Button OnClick="PrintSelectedNodes">Print Selected Nodes</Button>*@
|
||||
|
||||
<Button OnClick="DeselectAll">Deselect All</Button>
|
||||
<br />
|
||||
@ -55,49 +67,70 @@
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
@code{
|
||||
@code {
|
||||
|
||||
string printType;
|
||||
|
||||
List<string> printTexts = new List<string>();
|
||||
string[] printTexts;
|
||||
|
||||
Tree<string> tree;
|
||||
Tree<string> _tree;
|
||||
|
||||
private void PrintCheckedNodesTitle()
|
||||
{
|
||||
printType = "CheckedNodesTitle";
|
||||
printTexts = tree.CheckedTitles;
|
||||
}
|
||||
string[] expandedKeys;
|
||||
string[] checkedKeys;
|
||||
string[] selectedKeys;
|
||||
|
||||
bool autoExpandParent;
|
||||
|
||||
//private void PrintCheckedNodesTitle()
|
||||
//{
|
||||
// printType = "CheckedNodesTitle";
|
||||
// printTexts = tree.CheckedTitles;
|
||||
//}
|
||||
|
||||
private void PrintCheckedNodesKey()
|
||||
{
|
||||
printType = "CheckedNodesKey";
|
||||
printTexts = tree.CheckedKeys;
|
||||
printTexts = _tree.CheckedKeys;
|
||||
}
|
||||
|
||||
private void DecheckedAll()
|
||||
{
|
||||
tree.DecheckedAll();
|
||||
_tree.DecheckedAll();
|
||||
}
|
||||
|
||||
private void PrintSelectedNodes()
|
||||
{
|
||||
printType = "SelectedNodes";
|
||||
printTexts = tree.SelectedTitles;
|
||||
}
|
||||
//private void PrintSelectedNodes()
|
||||
//{
|
||||
// printType = "SelectedNodes";
|
||||
// printTexts = tree.SelectedTitles;
|
||||
//}
|
||||
|
||||
private void DeselectAll()
|
||||
{
|
||||
tree.DeselectAll();
|
||||
_tree.DeselectAll();
|
||||
}
|
||||
|
||||
private void ExpandAll()
|
||||
{
|
||||
tree.ExpandAll();
|
||||
_tree.ExpandAll();
|
||||
}
|
||||
|
||||
private void CollapseAll()
|
||||
{
|
||||
tree.CollapseAll();
|
||||
_tree.CollapseAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCheck(TreeEventArgs<string> e)
|
||||
{
|
||||
Console.WriteLine("OnCheck:" + e.Node.Key);
|
||||
}
|
||||
|
||||
private void OnSelect(TreeEventArgs<string> e)
|
||||
{
|
||||
Console.WriteLine("OnSelect:" + e.Node.Key);
|
||||
}
|
||||
|
||||
private void OnExpand((string[] ExpandedKeys, TreeNode<string> Node, bool Expanded) e)
|
||||
{
|
||||
Console.WriteLine("OnExpand:" + JsonSerializer.Serialize(e.ExpandedKeys));
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<h3>BigData</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
<Tree @ref="tree"
|
||||
ShowIcon DataSource="games"
|
||||
Multiple="@multiple"
|
||||
TitleExpression="x => x.DataItem.Text"
|
||||
ChildrenExpression="x => x.DataItem.Items"
|
||||
IconExpression="x => x.DataItem.Icon"
|
||||
IsLeafExpression="x => x.DataItem.Items?.Count == 0"
|
||||
KeyExpression="x => x.DataItem.Id"
|
||||
@bind-SelectedKey="@selectedKey"
|
||||
@bind-SelectedData="@selectedData"
|
||||
@bind-SelectedNode="@selectedNode"
|
||||
@bind-SelectedKeys="@selectedKeys"
|
||||
TItem="GameElement">
|
||||
</Tree>
|
||||
|
||||
<Divider>Single</Divider>
|
||||
<span>bind-SelectedKey:@selectedKey</span>
|
||||
<br />
|
||||
<span>bind-SelectedData:@(System.Text.Json.JsonSerializer.Serialize(selectedData))</span>
|
||||
<br />
|
||||
<span>bind-SelectedNode:@(System.Text.Json.JsonSerializer.Serialize(selectedNode?.Id))</span>
|
||||
<Divider>Multiple</Divider>
|
||||
<Switch @bind-Value="multiple" />Multiple
|
||||
<br />
|
||||
<span>bind-SelectedKeys:@(System.Text.Json.JsonSerializer.Serialize(selectedKeys))</span>
|
||||
<Divider>Action</Divider>
|
||||
<Button OnClick="AddSon">Add Son Node</Button>
|
||||
<Button OnClick="DeleteNode">Delete Node</Button>
|
||||
|
||||
@code{
|
||||
|
||||
private bool multiple;
|
||||
|
||||
Tree<GameElement> tree;
|
||||
|
||||
string selectedKey;
|
||||
|
||||
GameElement selectedData;
|
||||
|
||||
TreeNode<GameElement> selectedNode;
|
||||
|
||||
string[] selectedKeys;
|
||||
|
||||
|
||||
void AddSon()
|
||||
{
|
||||
if (selectedNode != null)
|
||||
{
|
||||
var id = new Random().Next(1000).ToString();
|
||||
selectedNode.DataItem.Items.Add(new GameElement(id, $"Node {id}")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
}); ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteNode()
|
||||
{
|
||||
if (selectedNode != null)
|
||||
{
|
||||
if (selectedNode.ParentNode != null)
|
||||
{
|
||||
selectedNode.ParentNode.DataItem.Items.Remove(selectedNode.DataItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree.DataSource.Remove(selectedNode.DataItem);
|
||||
}
|
||||
StateHasChanged();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
List<GameElement> games = new List<GameElement>()
|
||||
{
|
||||
new ("100","XBox","windows")
|
||||
{
|
||||
Items=new List<GameElement>()
|
||||
{
|
||||
new ("101","Halo"),
|
||||
new ("102","Gears of War"),
|
||||
new ("103","Forza Motosport"),
|
||||
}
|
||||
},
|
||||
new ("200","PlayStation","desktop")
|
||||
{
|
||||
Items=new List<GameElement>()
|
||||
{
|
||||
new ("201","Uncharted"),
|
||||
new ("202","God Of War"),
|
||||
new ("203","The Order:1886"),
|
||||
}
|
||||
},
|
||||
new ("300","Switch","mobile")
|
||||
{
|
||||
Items=new List<GameElement>()
|
||||
{
|
||||
new ("301","Super Mario Bros"),
|
||||
new ("302","The Legend of Zelda"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private record GameElement(string Id, string Text, string Icon = null)
|
||||
{
|
||||
public List<GameElement> Items { get; set; } = new List<GameElement>();
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<Tree TItem="string"
|
||||
ShowIcon
|
||||
DefaultExpandAll
|
||||
DefaultSelectedKeys="@(new[]{"0-0-0"})"
|
||||
>
|
||||
<SwitcherIconTemplate>
|
||||
@switcherIcon
|
||||
</SwitcherIconTemplate>
|
||||
<Nodes>
|
||||
<TreeNode Title="parent 1" Key="0-0" Icon="smile" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf" Key="0-0-0" Icon="meh" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="leaf" Key="0-0-1" TItem="string">
|
||||
<IconTemplate Context="node">
|
||||
@if (node.Selected)
|
||||
{
|
||||
<Icon Type="frown" Theme="fill" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="frown" Theme="outline" />
|
||||
}
|
||||
</IconTemplate>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</Tree>
|
||||
|
||||
@code {
|
||||
RenderFragment switcherIcon =@<Icon Type="down" />;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<DirectoryTree TItem="string"
|
||||
Multiple
|
||||
DefaultExpandAll
|
||||
OnSelect="OnSelect"
|
||||
OnExpand="OnExpand">
|
||||
<Nodes>
|
||||
<TreeNode Title="parent 0" Key="0-0" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf 0-0" Key="0-0-0" TItem="string" />
|
||||
<TreeNode Title="leaf 0-1" Key="0-0-1" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="parent 1" Key="0-1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf 1-0" Key="0-1-0" TItem="string" />
|
||||
<TreeNode Title="leaf 1-1" Key="0-1-1" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</DirectoryTree>
|
||||
|
||||
@code {
|
||||
void OnSelect()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OnExpand()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
<Tree @ref="tree" DefaultExpandAll Draggable BlockNode
|
||||
ShowIcon DataSource="games"
|
||||
TitleExpression="x => x.DataItem.Text"
|
||||
ChildrenExpression="x => x.DataItem.Items"
|
||||
IconExpression="x => x.DataItem.Icon"
|
||||
IsLeafExpression="x => x.DataItem.Items?.Count == 0"
|
||||
KeyExpression="x => x.DataItem.Id"
|
||||
TItem="GameElement" OnDragEnd="e=> { }" OnDrop="onDrop">
|
||||
</Tree>
|
||||
|
||||
@code{
|
||||
|
||||
Tree<GameElement> tree;
|
||||
|
||||
string selectedKey;
|
||||
|
||||
GameElement selectedData;
|
||||
|
||||
TreeNode<GameElement> selectedNode;
|
||||
|
||||
List<GameElement> games = new()
|
||||
{
|
||||
new ("0-0","0-0")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
{
|
||||
new ("0-0-0","0-0-0")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
{
|
||||
new ("0-0-0-0","0-0-0-0"),
|
||||
new ("0-0-0-1","0-0-0-1"),
|
||||
new ("0-0-0-2","0-0-0-2"),
|
||||
}
|
||||
},
|
||||
new ("0-0-1","0-0-1")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
{
|
||||
new ("0-0-1-0","0-0-1-0"),
|
||||
new ("0-0-1-1","0-0-1-1"),
|
||||
new ("0-0-1-2","0-0-1-2"),
|
||||
}
|
||||
},
|
||||
new ("0-0-2","0-0-2")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
{
|
||||
new ("0-0-2-0","0-0-2-0"),
|
||||
new ("0-0-2-1","0-0-2-1"),
|
||||
new ("0-0-2-2","0-0-2-2"),
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
new ("0-1","0-1")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
{
|
||||
new ("0-1-0","0-1-0"),
|
||||
new ("0-1-1","0-1-0"),
|
||||
new ("0-1-2","0-1-2"),
|
||||
}
|
||||
},
|
||||
new ("0-2","0-2")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
{
|
||||
new ("0-2-0","0-2-0"),
|
||||
new ("0-2-1","0-2-1"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private record GameElement(string Id, string Text, string Icon = null)
|
||||
{
|
||||
public List<GameElement> Items { get; set; } = new List<GameElement>();
|
||||
}
|
||||
|
||||
void onDrop(TreeEventArgs<GameElement> e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
|
||||
public async Task OnNodeLoadDelayAsync(TreeEventArgs<Data> args)
|
||||
{
|
||||
await Task.Delay(2000);//模拟异步执行
|
||||
await Task.Delay(1500);
|
||||
|
||||
var dataItem = ((Data)args.Node.DataItem);
|
||||
dataItem.Childs.Clear();
|
||||
|
@ -1,53 +0,0 @@
|
||||
<Tree Checkable BlockNode
|
||||
OnClick='e=>EventRecord(e,"OnClick")'
|
||||
OnDblClick='e=>EventRecord(e,"OnDblClick")'
|
||||
OnContextMenu='e=>EventRecord(e,"OnContextMenu")'
|
||||
OnCheckBoxChanged='e=>EventRecord(e,"OnCheckBoxChange")'
|
||||
OnExpandChanged='e=>EventRecord(e,"OnExpandChange")' TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A1-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A2" Disabled TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A2-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A2-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A3" DisableCheckbox TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A3-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-2" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-3" Disabled TItem="string"></TreeNode>
|
||||
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="B" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</Tree>
|
||||
<br />
|
||||
<span>Events</span>
|
||||
<div style="width:100%;height:150px;overflow-y:scroll">
|
||||
<ul>
|
||||
@foreach (var item in events)
|
||||
{
|
||||
<li>@item</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@code{
|
||||
public List<string> events { get; set; } = new List<string>();
|
||||
|
||||
public void EventRecord(TreeEventArgs<string> args, string eventName)
|
||||
{
|
||||
events.Insert(0, $"{eventName}:{args.Node.Title}");
|
||||
}
|
||||
}
|
@ -1,38 +1,74 @@
|
||||
<Switch @bind-Value="@_showLine"/>
|
||||
<br />
|
||||
<div>
|
||||
<div style="margin-bottom: 16px">
|
||||
showLine: <Switch @bind-Checked="_showLine" />
|
||||
<br />
|
||||
<br />
|
||||
showIcon: <Switch @bind-Checked="_showIcon" />
|
||||
<br />
|
||||
<br />
|
||||
showLeafIcon: <Switch @bind-Checked="_showLeafIcon" />
|
||||
</div>
|
||||
|
||||
<Tree ShowLine="@_showLine" Checkable TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A1-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A2" Disabled TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A2-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A2-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A3" DisableCheckbox TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A3-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-2" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-3" Disabled TItem="string"></TreeNode>
|
||||
<Tree
|
||||
ShowLine="@_showLine"
|
||||
ShowIcon="@_showIcon"
|
||||
ShowLeafIcon="@_showLeafIcon"
|
||||
DefaultExpandedKeys="@(new[]{"0-0-0"})"
|
||||
OnSelect="OnSelect"
|
||||
TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="parent 1" Key="0-0" Icon="carry-out" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="parent 1-0" Key="0-0-0" Icon="carry-out" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf" Key="0-0-0-0" Icon="carry-out" TItem="string" />
|
||||
<TreeNode Key="0-0-0-1" Icon="carry-out" TItem="string">
|
||||
<TitleTemplate>
|
||||
<div>
|
||||
<div>multiple line title</div>
|
||||
<div>multiple line title</div>
|
||||
</div>
|
||||
</TitleTemplate>
|
||||
</TreeNode>
|
||||
<TreeNode Title="leaf" Key="0-0-0-2" Icon="carry-out" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="parent 1-1" Key="0-0-1" Icon="carry-out" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="left" Key="0-0-1-0" Icon="carry-out" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="parent 1-2" Key="0-0-2" Icon="carry-out" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf" Key="0-0-2-0" Icon="carry-out" TItem="string" />
|
||||
<TreeNode Title="leaf" Key="0-0-2-1" Icon="carry-out" TItem="string" SwitcherIcon="form" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="parent 2" Key="0-1" Icon="carry-out" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="parent 2-0" Key="0-1-0" Icon="carry-out" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf" Key="0-1-0-0" Icon="carry-out" TItem="string" />
|
||||
<TreeNode Title="leaf" Key="0-1-0-1" Icon="carry-out" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</Tree>
|
||||
</div>
|
||||
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="B" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</Tree>
|
||||
|
||||
@code{
|
||||
@code {
|
||||
bool _showLine = true;
|
||||
bool _showIcon = false;
|
||||
bool _showLeafIcon = true;
|
||||
|
||||
void OnSelect(TreeEventArgs<string> e)
|
||||
{
|
||||
Console.WriteLine(JsonSerializer.Serialize(e));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 修改
|
||||
en-US: Modify
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用Tree提供的方法修改内容
|
||||
|
||||
## en-US
|
||||
|
||||
Use the methods provided by Tree to modify the content
|
@ -1,121 +0,0 @@
|
||||
<Tree @ref="tree"
|
||||
SelectedKey="100"
|
||||
ShowIcon DataSource="games"
|
||||
TitleExpression="x => x.DataItem.Text"
|
||||
ChildrenExpression="x => x.DataItem.Items"
|
||||
IconExpression="x => x.DataItem.Icon"
|
||||
IsLeafExpression="x => x.DataItem.Items?.Count == 0"
|
||||
KeyExpression="x => x.DataItem.Id"
|
||||
@bind-SelectedNode="@selectedNode"
|
||||
TItem="GameElement">
|
||||
</Tree>
|
||||
|
||||
<Divider>Node Modify</Divider>
|
||||
<Button OnClick="AddSon">Add Son</Button>
|
||||
<Button OnClick="AddNext">Add Next</Button>
|
||||
<Button OnClick="AddPrevious">Add Previous</Button>
|
||||
<Button OnClick="RemoveSelf">Remove Self</Button>
|
||||
|
||||
<Divider>Node Move</Divider>
|
||||
<Button OnClick="NodeMove">Move To First Node Son</Button>
|
||||
<Button OnClick="NodeMoveUp">Move Up</Button>
|
||||
<Button OnClick="NodeMoveDown">Move Down</Button>
|
||||
<Button OnClick="NodeDowngrade">Downgrade</Button>
|
||||
<Button OnClick="NodeUpgrade">Upgrade</Button>
|
||||
|
||||
@code{
|
||||
Tree<GameElement> tree;
|
||||
|
||||
TreeNode<GameElement> selectedNode;
|
||||
|
||||
int i;
|
||||
|
||||
GameElement GenerateDataItem()
|
||||
{
|
||||
return new GameElement(i++.ToString(), $"Node {i}")
|
||||
{
|
||||
Items = new List<GameElement>()
|
||||
};
|
||||
}
|
||||
|
||||
void AddSon()
|
||||
{
|
||||
selectedNode?.AddChildNode(GenerateDataItem());
|
||||
}
|
||||
|
||||
void AddNext()
|
||||
{
|
||||
selectedNode?.AddNextNode(GenerateDataItem());
|
||||
}
|
||||
|
||||
void AddPrevious()
|
||||
{
|
||||
selectedNode?.AddPreviousNode(GenerateDataItem());
|
||||
}
|
||||
|
||||
void RemoveSelf()
|
||||
{
|
||||
selectedNode?.Remove();
|
||||
}
|
||||
|
||||
void NodeMove()
|
||||
{
|
||||
var firstNode = tree.ChildNodes.First();
|
||||
selectedNode?.MoveInto(firstNode);
|
||||
}
|
||||
|
||||
void NodeMoveUp()
|
||||
{
|
||||
selectedNode?.MoveUp();
|
||||
}
|
||||
|
||||
void NodeMoveDown()
|
||||
{
|
||||
selectedNode?.MoveDown();
|
||||
}
|
||||
|
||||
void NodeDowngrade()
|
||||
{
|
||||
selectedNode?.Downgrade();
|
||||
}
|
||||
|
||||
void NodeUpgrade()
|
||||
{
|
||||
selectedNode?.Upgrade();
|
||||
}
|
||||
|
||||
List<GameElement> games = new List<GameElement>()
|
||||
{
|
||||
new ("100","XBox","windows")
|
||||
{
|
||||
Items=new List<GameElement>()
|
||||
{
|
||||
new ("101","Halo"),
|
||||
new ("102","Gears of War"),
|
||||
new ("103","Forza Motosport"),
|
||||
}
|
||||
},
|
||||
new ("200","PlayStation","desktop")
|
||||
{
|
||||
Items=new List<GameElement>()
|
||||
{
|
||||
new ("201","Uncharted"),
|
||||
new ("202","God Of War"),
|
||||
new ("203","The Order:1886"),
|
||||
}
|
||||
},
|
||||
new ("300","Switch","mobile")
|
||||
{
|
||||
Items=new List<GameElement>()
|
||||
{
|
||||
new ("301","Super Mario Bros"),
|
||||
new ("302","The Legend of Zelda"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private record GameElement(string Id, string Text, string Icon = null)
|
||||
{
|
||||
public List<GameElement> Items { get; set; } = new List<GameElement>();
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
<Switch @bind-Value="@checkable" />Checkable
|
||||
<br />
|
||||
<Switch @bind-Value="@blockNode" />BlockNode
|
||||
<br />
|
||||
<Switch @bind-Value="@showExpand" />ShowExpand
|
||||
<br />
|
||||
<Switch @bind-Value="@showIcon" />ShowIcon
|
||||
<br />
|
||||
<Switch @bind-Value="@multiple" />Multiple
|
||||
<br />
|
||||
<br />
|
||||
<Tree Checkable="@checkable" BlockNode="@blockNode" ShowExpand="@showExpand" ShowIcon="@showIcon" Multiple="@multiple" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A" Icon="folder-open" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1" Icon="folder-open" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1-1" Icon="file" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A1-2" Icon="file" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A2" Icon="folder-open" Disabled TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A2-1" Icon="file" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A2-2" Icon="file" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A3" Icon="folder-open" DisableCheckbox TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A3-1" Icon="file" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-2" Icon="file" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-3" Icon="file" Disabled TItem="string"></TreeNode>
|
||||
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="B" Icon="folder-open" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</Tree>
|
||||
|
||||
@code
|
||||
{
|
||||
private bool checkable = true;
|
||||
|
||||
private bool blockNode = true;
|
||||
|
||||
private bool showExpand = true;
|
||||
|
||||
private bool showIcon = true;
|
||||
|
||||
private bool multiple;
|
||||
|
||||
}
|
@ -1,17 +1,10 @@
|
||||
<Search @bind-Value="@searchKey" Placeholder="Search.." />
|
||||
<Divider Text="Default search (case sensitive)"></Divider>
|
||||
<Tree ShowIcon SearchValue="@searchKey"
|
||||
<Tree ShowIcon SearchValue="@searchKey" MatchedStyle="color: #f50;"
|
||||
DataSource="games"
|
||||
TitleExpression="x => x.DataItem.Text"
|
||||
ChildrenExpression="x => x.DataItem.Items"
|
||||
IconExpression="x => x.DataItem.Icon"></Tree>
|
||||
<Divider Text="Custom search (Ignore case)"></Divider>
|
||||
<Tree ShowIcon SearchValue="@searchKey"
|
||||
DataSource="games"
|
||||
TitleExpression="x => x.DataItem.Text"
|
||||
ChildrenExpression="x => x.DataItem.Items"
|
||||
IconExpression="x => x.DataItem.Icon"
|
||||
SearchExpression="x=> x.DataItem.Text.ToLower().Contains(searchKey.ToLower())"></Tree>
|
||||
|
||||
@code{
|
||||
string searchKey;
|
@ -0,0 +1,41 @@
|
||||
<Tree TItem="string"
|
||||
ShowLine
|
||||
SwitcherIcon="down"
|
||||
DefaultExpandedKeys="@(new[]{"0-0-0"})"
|
||||
OnSelect="OnSelect">
|
||||
<SwitcherIconTemplate>
|
||||
<Icon Type="down" />
|
||||
</SwitcherIconTemplate>
|
||||
<Nodes>
|
||||
<TreeNode Title="parent 1" Key="0-0" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="parent 1-0" Key="0-0-0" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf" Key="0-0-0-0" TItem="string" />
|
||||
<TreeNode Title="leaf" Key="0-0-0-1" TItem="string" />
|
||||
<TreeNode Title="leaf" Key="0-0-0-2" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="parent 1-1" Key="0-0-1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf" Key="0-0-1-0" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="parent 1-2" Key="0-0-2" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="leaf" Key="0-0-2-0" TItem="string" />
|
||||
<TreeNode Title="leaf" Key="0-0-2-1" TItem="string" />
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
|
||||
</Nodes>
|
||||
</Tree>
|
||||
|
||||
@code {
|
||||
void OnSelect()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
<Tree Checkable ShowIcon TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A1-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A2-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A2" Disabled TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A2-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A2-2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="A3" DisableCheckbox TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="A3-1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-2" DisableCheckbox TItem="string"></TreeNode>
|
||||
<TreeNode Title="A3-3" Disabled TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
<TreeNode Title="B" TItem="string">
|
||||
<Nodes>
|
||||
<TreeNode Title="B1" TItem="string"></TreeNode>
|
||||
<TreeNode Title="B2" TItem="string"></TreeNode>
|
||||
</Nodes>
|
||||
</TreeNode>
|
||||
</Nodes>
|
||||
<IndentTemplate Context="node" >
|
||||
<span>--></span>
|
||||
</IndentTemplate>
|
||||
<TitleTemplate Context="node">
|
||||
<span style="color:@(node.Title?.FirstOrDefault() switch {'A'=>"red",'B'=>"green",_=>"blue" })">@node.Title</span>
|
||||
</TitleTemplate>
|
||||
<TitleIconTemplate Context="node">
|
||||
@if (node.IsLeaf)
|
||||
{
|
||||
<Icon Type="@(node.Title?.FirstOrDefault() switch {'A'=>"user-delete",'B'=>"tag",_=>"" })" Theme="outline" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="@(node.Title?.FirstOrDefault() switch {'A'=>"usergroup-delete",'B'=>"tags",_=>"" })" Theme="outline" />
|
||||
}
|
||||
</TitleIconTemplate>
|
||||
<SwitcherIconTemplate Context="node">
|
||||
@if (node.Expanded)
|
||||
{
|
||||
<Icon Type="down-circle" Theme="outline" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<Icon Type="right-circle" Theme="outline" />
|
||||
}
|
||||
</SwitcherIconTemplate>
|
||||
</Tree>
|
@ -0,0 +1,5 @@
|
||||
<h3>VirtualScroll</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 受控操作示例
|
||||
en-US: Controlled Tree
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
受控操作示例
|
||||
|
||||
## en-US
|
||||
|
||||
Controlled mode lets parent nodes reflect the status of child nodes more intelligently.
|
||||
|
@ -11,4 +11,4 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
The most basic usage, tell you how to use checkable, selectable, disabled, defaultExpandKeys, and etc.
|
||||
The most basic usage, tell you how to use checkable, selectable, disabled, defaultExpandKeys, and etc.
|
||||
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 受控操作示例
|
||||
en-US: basic controlled example
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
受控操作示例(默认)。
|
||||
|
||||
## en-US
|
||||
|
||||
basic controlled example.
|
42
site/AntDesign.Docs/Demos/Components/Tree/demo/big-data.md
Normal file
42
site/AntDesign.Docs/Demos/Components/Tree/demo/big-data.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
order: 99
|
||||
title:
|
||||
zh-CN: 大数据
|
||||
en-US: Big data
|
||||
debug: true
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
大数据展示。
|
||||
|
||||
## en-US
|
||||
|
||||
Plenty of tree nodes.
|
||||
|
||||
```jsx
|
||||
import { Tree } from 'antd';
|
||||
|
||||
const treeData = [];
|
||||
|
||||
for (let i = 0; i < 100; i += 1) {
|
||||
const children = [];
|
||||
|
||||
for (let j = 0; j < 100; j += 1) {
|
||||
children.push({
|
||||
title: `child ${i}-${j}`,
|
||||
key: `l-${i}-${j}`,
|
||||
});
|
||||
}
|
||||
|
||||
treeData.push({
|
||||
title: `parent ${i}`,
|
||||
key: `l-${i}`,
|
||||
children,
|
||||
});
|
||||
}
|
||||
|
||||
const Demo = () => <Tree defaultExpandAll height={400} treeData={treeData} />;
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 绑定
|
||||
en-US: Bind
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
绑定数据创建树
|
||||
|
||||
## en-US
|
||||
|
||||
Bind data to create a tree
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 自定义图标
|
||||
en-US: Customize Icon
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以针对不同的节点定制图标。
|
||||
|
||||
## en-US
|
||||
|
||||
You can customize icons for different nodes.
|
||||
|
15
site/AntDesign.Docs/Demos/Components/Tree/demo/directory.md
Normal file
15
site/AntDesign.Docs/Demos/Components/Tree/demo/directory.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 目录
|
||||
en-US: directory
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
内置的目录树,`multiple` 模式支持 `ctrl(Windows)` / `command(Mac)` 复选。
|
||||
|
||||
## en-US
|
||||
|
||||
Built-in directory tree. `multiple` support `ctrl(Windows)` / `command(Mac)` selection.
|
||||
|
141
site/AntDesign.Docs/Demos/Components/Tree/demo/draggable.md
Normal file
141
site/AntDesign.Docs/Demos/Components/Tree/demo/draggable.md
Normal file
@ -0,0 +1,141 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 拖动示例
|
||||
en-US: draggable
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
将节点拖拽到其他节点内部或前后。
|
||||
|
||||
## en-US
|
||||
|
||||
Drag treeNode to insert after the other treeNode or insert into the other parent TreeNode.
|
||||
|
||||
```jsx
|
||||
import { Tree } from 'antd';
|
||||
|
||||
const x = 3;
|
||||
const y = 2;
|
||||
const z = 1;
|
||||
const gData = [];
|
||||
|
||||
const generateData = (_level, _preKey, _tns) => {
|
||||
const preKey = _preKey || '0';
|
||||
const tns = _tns || gData;
|
||||
|
||||
const children = [];
|
||||
for (let i = 0; i < x; i++) {
|
||||
const key = `${preKey}-${i}`;
|
||||
tns.push({ title: key, key });
|
||||
if (i < y) {
|
||||
children.push(key);
|
||||
}
|
||||
}
|
||||
if (_level < 0) {
|
||||
return tns;
|
||||
}
|
||||
const level = _level - 1;
|
||||
children.forEach((key, index) => {
|
||||
tns[index].children = [];
|
||||
return generateData(level, key, tns[index].children);
|
||||
});
|
||||
};
|
||||
generateData(z);
|
||||
|
||||
class Demo extends React.Component {
|
||||
state = {
|
||||
gData,
|
||||
expandedKeys: ['0-0', '0-0-0', '0-0-0-0'],
|
||||
};
|
||||
|
||||
onDragEnter = info => {
|
||||
console.log(info);
|
||||
// expandedKeys 需要受控时设置
|
||||
// this.setState({
|
||||
// expandedKeys: info.expandedKeys,
|
||||
// });
|
||||
};
|
||||
|
||||
onDrop = info => {
|
||||
console.log(info);
|
||||
const dropKey = info.node.key;
|
||||
const dragKey = info.dragNode.key;
|
||||
const dropPos = info.node.pos.split('-');
|
||||
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
|
||||
|
||||
const loop = (data, key, callback) => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].key === key) {
|
||||
return callback(data[i], i, data);
|
||||
}
|
||||
if (data[i].children) {
|
||||
loop(data[i].children, key, callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
const data = [...this.state.gData];
|
||||
|
||||
// Find dragObject
|
||||
let dragObj;
|
||||
loop(data, dragKey, (item, index, arr) => {
|
||||
arr.splice(index, 1);
|
||||
dragObj = item;
|
||||
});
|
||||
|
||||
if (!info.dropToGap) {
|
||||
// Drop on the content
|
||||
loop(data, dropKey, item => {
|
||||
item.children = item.children || [];
|
||||
// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
});
|
||||
} else if (
|
||||
(info.node.props.children || []).length > 0 && // Has children
|
||||
info.node.props.expanded && // Is expanded
|
||||
dropPosition === 1 // On the bottom gap
|
||||
) {
|
||||
loop(data, dropKey, item => {
|
||||
item.children = item.children || [];
|
||||
// where to insert 示例添加到头部,可以是随意位置
|
||||
item.children.unshift(dragObj);
|
||||
// in previous version, we use item.children.push(dragObj) to insert the
|
||||
// item to the tail of the children
|
||||
});
|
||||
} else {
|
||||
let ar;
|
||||
let i;
|
||||
loop(data, dropKey, (item, index, arr) => {
|
||||
ar = arr;
|
||||
i = index;
|
||||
});
|
||||
if (dropPosition === -1) {
|
||||
ar.splice(i, 0, dragObj);
|
||||
} else {
|
||||
ar.splice(i + 1, 0, dragObj);
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
gData: data,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Tree
|
||||
className="draggable-tree"
|
||||
defaultExpandedKeys={this.state.expandedKeys}
|
||||
draggable
|
||||
blockNode
|
||||
onDragEnter={this.onDragEnter}
|
||||
onDrop={this.onDrop}
|
||||
treeData={this.state.gData}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 2
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 异步数据加载
|
||||
en-US: load data asynchronously
|
||||
@ -11,4 +11,5 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
To load data asynchronously when click to expand a treeNode.
|
||||
To load data asynchronously when click to expand a treeNode.
|
||||
|
||||
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 事件
|
||||
en-US: Event
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
Tree的事件
|
||||
|
||||
## en-US
|
||||
|
||||
Tree events
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
order: 6
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: 连接线
|
||||
en-US: Tree with line
|
||||
@ -11,4 +11,117 @@ title:
|
||||
|
||||
## en-US
|
||||
|
||||
Tree with connected line between nodes, turn on by `showLine`, customize the preseted icon by `switcherIcon`.
|
||||
Tree with connected line between nodes, turn on by `showLine`, customize the preseted icon by `switcherIcon`.
|
||||
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { Tree, Switch } from 'antd';
|
||||
import { CarryOutOutlined, FormOutlined } from '@ant-design/icons';
|
||||
|
||||
const treeData = [
|
||||
{
|
||||
title: 'parent 1',
|
||||
key: '0-0',
|
||||
icon: <CarryOutOutlined />,
|
||||
children: [
|
||||
{
|
||||
title: 'parent 1-0',
|
||||
key: '0-0-0',
|
||||
icon: <CarryOutOutlined />,
|
||||
children: [
|
||||
{ title: 'leaf', key: '0-0-0-0', icon: <CarryOutOutlined /> },
|
||||
{
|
||||
title: (
|
||||
<>
|
||||
<div>multiple line title</div>
|
||||
<div>multiple line title</div>
|
||||
</>
|
||||
),
|
||||
key: '0-0-0-1',
|
||||
icon: <CarryOutOutlined />,
|
||||
},
|
||||
{ title: 'leaf', key: '0-0-0-2', icon: <CarryOutOutlined /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'parent 1-1',
|
||||
key: '0-0-1',
|
||||
icon: <CarryOutOutlined />,
|
||||
children: [{ title: 'leaf', key: '0-0-1-0', icon: <CarryOutOutlined /> }],
|
||||
},
|
||||
{
|
||||
title: 'parent 1-2',
|
||||
key: '0-0-2',
|
||||
icon: <CarryOutOutlined />,
|
||||
children: [
|
||||
{ title: 'leaf', key: '0-0-2-0', icon: <CarryOutOutlined /> },
|
||||
{
|
||||
title: 'leaf',
|
||||
key: '0-0-2-1',
|
||||
icon: <CarryOutOutlined />,
|
||||
switcherIcon: <FormOutlined />,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'parent 2',
|
||||
key: '0-1',
|
||||
icon: <CarryOutOutlined />,
|
||||
children: [
|
||||
{
|
||||
title: 'parent 2-0',
|
||||
key: '0-1-0',
|
||||
icon: <CarryOutOutlined />,
|
||||
children: [
|
||||
{ title: 'leaf', key: '0-1-0-0', icon: <CarryOutOutlined /> },
|
||||
{ title: 'leaf', key: '0-1-0-1', icon: <CarryOutOutlined /> },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const Demo: React.FC<{}> = () => {
|
||||
const [showLine, setShowLine] = useState<boolean | { showLeafIcon: boolean }>(true);
|
||||
const [showIcon, setShowIcon] = useState<boolean>(false);
|
||||
const [showLeafIcon, setShowLeafIcon] = useState<boolean>(true);
|
||||
|
||||
const onSelect = (selectedKeys: React.Key[], info: any) => {
|
||||
console.log('selected', selectedKeys, info);
|
||||
};
|
||||
|
||||
const onSetLeafIcon = (checked: boolean) => {
|
||||
setShowLeafIcon(checked);
|
||||
setShowLine({ showLeafIcon: checked });
|
||||
};
|
||||
|
||||
const onSetShowLine = (checked: boolean) => {
|
||||
setShowLine(checked ? { showLeafIcon } : false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
showLine: <Switch checked={!!showLine} onChange={onSetShowLine} />
|
||||
<br />
|
||||
<br />
|
||||
showIcon: <Switch checked={showIcon} onChange={setShowIcon} />
|
||||
<br />
|
||||
<br />
|
||||
showLeafIcon: <Switch checked={showLeafIcon} onChange={onSetLeafIcon} />
|
||||
</div>
|
||||
<Tree
|
||||
showLine={showLine}
|
||||
showIcon={showIcon}
|
||||
defaultExpandedKeys={['0-0-0']}
|
||||
onSelect={onSelect}
|
||||
treeData={treeData}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
||||
|
@ -1,13 +0,0 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 属性
|
||||
en-US: Property
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
|
||||
|
||||
## en-US
|
||||
|
161
site/AntDesign.Docs/Demos/Components/Tree/demo/search.md
Normal file
161
site/AntDesign.Docs/Demos/Components/Tree/demo/search.md
Normal file
@ -0,0 +1,161 @@
|
||||
---
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 可搜索
|
||||
en-US: Searchable
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可搜索的树。
|
||||
|
||||
## en-US
|
||||
|
||||
Searchable Tree.
|
||||
|
||||
```jsx
|
||||
import { Tree, Input } from 'antd';
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
const x = 3;
|
||||
const y = 2;
|
||||
const z = 1;
|
||||
const gData = [];
|
||||
|
||||
const generateData = (_level, _preKey, _tns) => {
|
||||
const preKey = _preKey || '0';
|
||||
const tns = _tns || gData;
|
||||
|
||||
const children = [];
|
||||
for (let i = 0; i < x; i++) {
|
||||
const key = `${preKey}-${i}`;
|
||||
tns.push({ title: key, key });
|
||||
if (i < y) {
|
||||
children.push(key);
|
||||
}
|
||||
}
|
||||
if (_level < 0) {
|
||||
return tns;
|
||||
}
|
||||
const level = _level - 1;
|
||||
children.forEach((key, index) => {
|
||||
tns[index].children = [];
|
||||
return generateData(level, key, tns[index].children);
|
||||
});
|
||||
};
|
||||
generateData(z);
|
||||
|
||||
const dataList = [];
|
||||
const generateList = data => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const node = data[i];
|
||||
const { key } = node;
|
||||
dataList.push({ key, title: key });
|
||||
if (node.children) {
|
||||
generateList(node.children);
|
||||
}
|
||||
}
|
||||
};
|
||||
generateList(gData);
|
||||
|
||||
const getParentKey = (key, tree) => {
|
||||
let parentKey;
|
||||
for (let i = 0; i < tree.length; i++) {
|
||||
const node = tree[i];
|
||||
if (node.children) {
|
||||
if (node.children.some(item => item.key === key)) {
|
||||
parentKey = node.key;
|
||||
} else if (getParentKey(key, node.children)) {
|
||||
parentKey = getParentKey(key, node.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
return parentKey;
|
||||
};
|
||||
|
||||
class SearchTree extends React.Component {
|
||||
state = {
|
||||
expandedKeys: [],
|
||||
searchValue: '',
|
||||
autoExpandParent: true,
|
||||
};
|
||||
|
||||
onExpand = expandedKeys => {
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: false,
|
||||
});
|
||||
};
|
||||
|
||||
onChange = e => {
|
||||
const { value } = e.target;
|
||||
const expandedKeys = dataList
|
||||
.map(item => {
|
||||
if (item.title.indexOf(value) > -1) {
|
||||
return getParentKey(item.key, gData);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((item, i, self) => item && self.indexOf(item) === i);
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
searchValue: value,
|
||||
autoExpandParent: true,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { searchValue, expandedKeys, autoExpandParent } = this.state;
|
||||
const loop = data =>
|
||||
data.map(item => {
|
||||
const index = item.title.indexOf(searchValue);
|
||||
const beforeStr = item.title.substr(0, index);
|
||||
const afterStr = item.title.substr(index + searchValue.length);
|
||||
const title =
|
||||
index > -1 ? (
|
||||
<span>
|
||||
{beforeStr}
|
||||
<span className="site-tree-search-value">{searchValue}</span>
|
||||
{afterStr}
|
||||
</span>
|
||||
) : (
|
||||
<span>{item.title}</span>
|
||||
);
|
||||
if (item.children) {
|
||||
return { title, key: item.key, children: loop(item.children) };
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
key: item.key,
|
||||
};
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
<Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChange} />
|
||||
<Tree
|
||||
onExpand={this.onExpand}
|
||||
expandedKeys={expandedKeys}
|
||||
autoExpandParent={autoExpandParent}
|
||||
treeData={loop(gData)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<SearchTree />, mountNode);
|
||||
```
|
||||
|
||||
```css
|
||||
.site-tree-search-value {
|
||||
color: #f50;
|
||||
}
|
||||
```
|
||||
|
||||
<style>
|
||||
[data-theme="dark"] .site-tree-search-value {
|
||||
color: #d84a1b;
|
||||
}
|
||||
</style>
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 5
|
||||
title:
|
||||
zh-CN: 可搜索
|
||||
en-US: Searchable
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可搜索的树。
|
||||
|
||||
## en-US
|
||||
|
||||
Searchable Tree.
|
@ -0,0 +1,88 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 自定义展开/折叠图标
|
||||
en-US: Customize collapse/expand icon
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
自定义展开/折叠图标。
|
||||
|
||||
## en-US
|
||||
|
||||
customize collapse/expand icon of tree node
|
||||
|
||||
```jsx
|
||||
import { Tree } from 'antd';
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
class Demo extends React.Component {
|
||||
onSelect = (selectedKeys, info) => {
|
||||
console.log('selected', selectedKeys, info);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Tree
|
||||
showLine
|
||||
switcherIcon={<DownOutlined />}
|
||||
defaultExpandedKeys={['0-0-0']}
|
||||
onSelect={this.onSelect}
|
||||
treeData={[
|
||||
{
|
||||
title: 'parent 1',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{
|
||||
title: 'parent 1-0',
|
||||
key: '0-0-0',
|
||||
children: [
|
||||
{
|
||||
title: 'leaf',
|
||||
key: '0-0-0-0',
|
||||
},
|
||||
{
|
||||
title: 'leaf',
|
||||
key: '0-0-0-1',
|
||||
},
|
||||
{
|
||||
title: 'leaf',
|
||||
key: '0-0-0-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'parent 1-1',
|
||||
key: '0-0-1',
|
||||
children: [
|
||||
{
|
||||
title: 'leaf',
|
||||
key: '0-0-1-0',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'parent 1-2',
|
||||
key: '0-0-2',
|
||||
children: [
|
||||
{
|
||||
title: 'leaf',
|
||||
key: '0-0-2-0',
|
||||
},
|
||||
{
|
||||
title: 'leaf',
|
||||
key: '0-0-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<Demo />, mountNode);
|
||||
```
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 模板
|
||||
en-US: Template
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用模板重新定义树中的各元素显示内容
|
||||
|
||||
## en-US
|
||||
|
||||
Use templates to redefine the display content of each element in the tree
|
@ -0,0 +1,40 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 虚拟滚动
|
||||
en-US: Virtual scroll
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `height` 属性则切换为虚拟滚动。
|
||||
|
||||
## en-US
|
||||
|
||||
Use virtual list through `height` prop.
|
||||
|
||||
```jsx
|
||||
import { Tree } from 'antd';
|
||||
|
||||
function dig(path = '0', level = 3) {
|
||||
const list = [];
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
const key = `${path}-${i}`;
|
||||
const treeNode = {
|
||||
title: key,
|
||||
key,
|
||||
};
|
||||
|
||||
if (level > 0) {
|
||||
treeNode.children = dig(key, level - 1);
|
||||
}
|
||||
|
||||
list.push(treeNode);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
const treeData = dig();
|
||||
|
||||
ReactDOM.render(<Tree treeData={treeData} height={233} defaultExpandAll />, mountNode);
|
||||
```
|
@ -16,4 +16,94 @@ Almost anything can be represented in a tree structure. Examples include directo
|
||||
### Tree props
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| ShowExpand | Shows an expansion icon before the node | boolean | true | |
|
||||
| ShowLine | Shows a connecting line | boolean | false | |
|
||||
| Disabled | The tree is disabled | boolean | false | |
|
||||
| ShowIcon | show treeNode icon icon | boolean | false | |
|
||||
| Draggable | Whether the node allows drag and drop | boolean | false | |
|
||||
| BlockNode | Whether treeNode fill remaining horizontal space | boolean | false | |
|
||||
| ShowLeafIcon | Displays the cotyledon icon | boolean | false | |
|
||||
| SwitcherIcon | Customize toggle icon£¬the value is Icon types | string | null | |
|
||||
| Selectable | Whether can be selected | boolean | true | |
|
||||
| DefaultSelectedKeys | Specifies the keys of the default selected treeNodes | string[] | null | |
|
||||
| Multiple | Allows selecting multiple treeNodes | boolean | false | |
|
||||
| Checkable | Add a Checkbox before the node | boolean | false | |
|
||||
| CheckStrictly | Check treeNode precisely; parent treeNode and children treeNodes are not associated | boolean | false | |
|
||||
| DefaultCheckedKeys | Specifies the keys of the default checked treeNodes | string[] | null | |
|
||||
| DisableCheckKeys | Disable node Checkbox | string[] | null | |
|
||||
| SearchValue | search value | string | null | |
|
||||
| MatchedStyle | Search for matching text styles | string | null | |
|
||||
| DataSource | bing datasource | List | null | |
|
||||
| TitleExpression | Specifies a method that returns the text of the node. | Func | | |
|
||||
| KeyExpression | Specifies a method that returns the key of the node. | Func | | |
|
||||
| IconExpression | Specifies a method to return the node icon. | Func | | |
|
||||
| IsLeafExpression | Specifies a method that returns whether the expression is a leaf node. | Func | | |
|
||||
| ChildrenExpression | Specifies a method to return a child node | Func | | |
|
||||
| DisabledExpression | Specifies a method to return a disabled node | Func | | |
|
||||
| DefaultExpandAll | All tree nodes are expanded by default | boolean | false | |
|
||||
| DefaultExpandParent | The parent node is expanded by default | boolean | false | |
|
||||
| DefaultExpandedKeys | Expand the specified tree node by default | string[] | null | |
|
||||
| ExpandedKeys | (Controlled) expands the specified tree node | string[] | null | |
|
||||
| AutoExpandParent | Whether to automatically expand a parent treeNode | bool | false | |
|
||||
|
||||
### Bind °ó¶¨Öµ
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| @bind-SelectedKey | SelectedKey | string | | |
|
||||
| @bind-SelectedNode | SelectedNode | TreeNode | | |
|
||||
| @bind-SelectedData | SelectedData | string | | |
|
||||
| @bind-SelectedKeys | SelectedKeys | string[] | | |
|
||||
| @bind-SelectedDatas | SelectedDatas | TItem[] | | |
|
||||
| @bind-CheckedKeys | CheckedKeys | string[] | | |
|
||||
|
||||
### Tree EventCallback
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| OnNodeLoadDelayAsync | Lazy load callbacks ¡£You must use async and the return type is Task, otherwise you may experience load lag and display problems | EventCallback | | |
|
||||
| OnClick | Click the tree node callback | EventCallback | | |
|
||||
| OnDblClick | Double-click the node callback | EventCallback | | |
|
||||
| OnContextMenu | Right-click tree node callback | EventCallback | | |
|
||||
| OnCheckBoxChanged | checked the tree node callback | EventCallback | | |
|
||||
| OnExpandChanged | Click the expansion tree node icon to call back | EventCallback | | |
|
||||
| OnDragStart | Called when the drag and drop begins | EventCallback | | |
|
||||
| OnDragEnter | Called when drag and drop into a releasable target | EventCallback | | |
|
||||
| OnDragLeave | Called when drag and drop away from a releasable target | EventCallback | | |
|
||||
| OnDrop | Triggered when drag-and-drop drops succeed | EventCallback | | |
|
||||
| OnDragEnd | Drag-and-drop end callback ¡£this callback method must be set | EventCallback | | |
|
||||
|
||||
### Tree Functions
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| ExpandAll | All tree nodes are expanded by default | void | | |
|
||||
| CollapseAll | The parent node is expanded by default | void | | |
|
||||
|
||||
### Tree RenderFragment
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| IndentTemplate | The indentation template | RenderFragment | | |
|
||||
| TitleTemplate | Customize the header template | RenderFragment | | |
|
||||
| TitleIconTemplate | Customize the icon templates | RenderFragment | | |
|
||||
| SwitcherIconTemplate | Customize toggle icon templates | RenderFragment | | |
|
||||
|
||||
|
||||
|
||||
### TreeNode props
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Key | key | string | | |
|
||||
| Disabled | disabled | string | | |
|
||||
| Checked | checked | boolean | false | |
|
||||
| DisableCheckbox | | boolean | false | |
|
||||
| Title | title | string | false | |
|
||||
| TitleTemplate | title template | RenderFragment | null | |
|
||||
| Icon | icon | string | false | |
|
||||
| IconTemplate | icon template | RenderFragment | null | |
|
||||
| DataItem | dataitem | Type | | |
|
||||
| SwitcherIcon | Customize node toggle icon £¬the value is Icon types | string | null | |
|
||||
| SwitcherIconTemplate | SwitcherIcon template | RenderFragment | null | |
|
@ -17,4 +17,95 @@ cover: https://gw.alipayobjects.com/zos/alicdn/Xh-oWqg9k/Tree.svg
|
||||
### Tree props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| ShowExpand | 显示展开图标 | boolean | true | |
|
||||
| ShowLine | 显示连接线 | boolean | false | |
|
||||
| Disabled | 禁用 | boolean | false | |
|
||||
| ShowIcon | 显示节点图标 | boolean | false | |
|
||||
| Draggable | 是否允许拖拽 | boolean | false | |
|
||||
| BlockNode | 是否节点占据一行 | boolean | false | |
|
||||
| ShowLeafIcon | 显示子叶图标(如果 ShowLeafIcon 未赋值, 会等于 `ShowLine` 的值) | boolean | false | |
|
||||
| SwitcherIcon | 设置所有节点的展开图标,值 Icon 的 Type | string | null | |
|
||||
| Selectable |是否可以选择 | boolean | true | |
|
||||
| Multiple | 允许选择多个树节点 | boolean | false | |
|
||||
| Checkable | 节点前添加 Checkbox 复选框 | boolean | false | |
|
||||
| CheckStrictly | checkable 状态下节点选择完全受控(父子节点选中状态不再关联) | boolean | false | |
|
||||
| DefaultSelectedKeys | 默认选中的节点key | string[] | null | |
|
||||
| DefaultCheckedKeys | 默认勾选的节点key | string[] | null | |
|
||||
| DisableCheckKeys | 默认禁用的勾选节点 | string[] | null | |
|
||||
| SearchValue | 搜索节点关键字 | string | null | |
|
||||
| MatchedStyle | 搜索匹配关键字高亮样式 | string | null | |
|
||||
| DataSource | 数据源 | List | null | |
|
||||
| TitleExpression | 指定一个方法,该表达式返回节点的文本。 | Func | | |
|
||||
| KeyExpression | 指定一个返回节点Key的方法。 | Func | | |
|
||||
| IconExpression | 指定一个返回节点名称的方法。 | Func | | |
|
||||
| IsLeafExpression | 返回一个值是否是页节点 | Func | | |
|
||||
| ChildrenExpression | 返回子节点的方法 | Func | | |
|
||||
| DisabledExpression | 指定一个返回禁用节点的方法 | Func | | |
|
||||
| DefaultExpandAll | 默认展开所有节点 | boolean | false | |
|
||||
| DefaultExpandParent | 默认展开顶级父节点 | boolean | false | |
|
||||
| DefaultExpandedKeys | 默认展开的节点数 | string[] | null | |
|
||||
| ExpandedKeys | (受控)展开指定的树节点 | string[] | null | |
|
||||
| AutoExpandParent | 是否自动展开父节点 | bool | false | |
|
||||
|
||||
|
||||
### Bind 绑定值
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| @bind-SelectedKey | 绑定选择的节点Key | string | | |
|
||||
| @bind-SelectedNode | 绑定选择的节点 | TreeNode | | |
|
||||
| @bind-SelectedData | 绑定选择的节点数据项 | string | | |
|
||||
| @bind-SelectedKeys | 绑定选择的节点Key集合 | string[] | | |
|
||||
| @bind-SelectedDatas | 绑定选择的节点数据项 | TItem[] | | |
|
||||
| @bind-CheckedKeys | 绑定勾选的数据 keys | string[] | | |
|
||||
|
||||
### Tree EventCallback
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| OnNodeLoadDelayAsync | 异步加载书回调,方法异步使用 async | EventCallback | | |
|
||||
| OnClick | 点击节点回调 | EventCallback | | |
|
||||
| OnDblClick | 双击节点回调 | EventCallback | | |
|
||||
| OnContextMenu | 右键回调 | EventCallback | | |
|
||||
| OnCheckBoxChanged | 节点勾选回调 | EventCallback | | |
|
||||
| OnExpandChanged | 展开节点回调 | EventCallback | | |
|
||||
| OnDragStart | 拖拽开始回调 | EventCallback | | |
|
||||
| OnDragEnter | 拖拽开始进入目标节点回调 | EventCallback | | |
|
||||
| OnDragLeave | 拖拽离开目标节点回调 | EventCallback | | |
|
||||
| OnDrop | 拖拽录入目标节点回调 | EventCallback | | |
|
||||
| OnDragEnd | 拖拽结束回调(此回调方法必须设置) | EventCallback | | |
|
||||
|
||||
### Tree Functions
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| ExpandAll | 展开所有节点 | void | | |
|
||||
| CollapseAll | 关闭所有节点 | void | | |
|
||||
|
||||
### Tree RenderFragment
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| IndentTemplate | 自定义缩进模板 | RenderFragment | | |
|
||||
| TitleTemplate | 自定义标题模板 | RenderFragment | | |
|
||||
| TitleIconTemplate | 自定义标题Icon | RenderFragment | | |
|
||||
| SwitcherIconTemplate | 自定义展开图标 | RenderFragment | | |
|
||||
|
||||
|
||||
### TreeNode props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Key | 节点key | string | | |
|
||||
| Disabled | 是否禁用 | string | | |
|
||||
| Checked | 勾选 | boolean | false | |
|
||||
| DisableCheckbox | 禁用复选框 | boolean | false | |
|
||||
| Checked | 勾选 | boolean | false | |
|
||||
| Title | 标题 | string | false | |
|
||||
| TitleTemplate | 标题模板 | RenderFragment | null | |
|
||||
| Icon | 标题前图标 | string | false | |
|
||||
| IconTemplate | 标题前图标模板 | RenderFragment | null | |
|
||||
| DataItem | 数据项 | Type | | |
|
||||
| SwitcherIcon | 该节点的展开图标 | string | null | |
|
||||
| SwitcherIconTemplate | 该节点的展开图标 | RenderFragment | null | |
|
Loading…
Reference in New Issue
Block a user