2020-05-26 15:21:47 +08:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
2020-09-16 13:58:16 +08:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.AspNetCore.Components;
|
|
|
|
|
using Microsoft.AspNetCore.Components.Web;
|
|
|
|
|
using OneOf;
|
2020-05-26 15:21:47 +08:00
|
|
|
|
|
2020-05-29 00:33:49 +08:00
|
|
|
|
namespace AntDesign
|
2020-05-26 15:21:47 +08:00
|
|
|
|
{
|
|
|
|
|
public partial class Transfer : AntDomComponentBase
|
|
|
|
|
{
|
|
|
|
|
private const string PrefixName = "ant-transfer";
|
|
|
|
|
private const string DisabledClass = "ant-transfer-list-content-item-disabled";
|
|
|
|
|
private const string FooterClass = "ant-transfer-list-with-footer";
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public IList<TransferItem> DataSource { get; set; }
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public string[] Titles { get; set; } = new string[2];
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public string[] Operations { get; set; } = new string[2];
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public bool Disabled { get; set; } = false;
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public bool ShowSearch { get; set; } = false;
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public bool ShowSelectAll { get; set; } = true;
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public string[] TargetKeys { get; set; }
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public string[] SelectedKeys { get; set; }
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public EventCallback<TransferChangeArgs> OnChange { get; set; }
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public EventCallback<TransferScrollArgs> OnScroll { get; set; }
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public EventCallback<TransferSearchArgs> OnSearch { get; set; }
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public EventCallback<TransferSelectChangeArgs> OnSelectChange { get; set; }
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public Func<TransferItem, OneOf<string, RenderFragment>> Render { get; set; }
|
|
|
|
|
|
2020-10-24 13:39:02 +08:00
|
|
|
|
[Parameter]
|
|
|
|
|
public TransferLocale Locale { get; set; } = LocaleProvider.CurrentLocale.Transfer;
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
[Parameter]
|
2020-09-16 13:58:16 +08:00
|
|
|
|
public string Footer { get; set; } = string.Empty;
|
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public RenderFragment FooterTemplate { get; set; }
|
2020-05-26 15:21:47 +08:00
|
|
|
|
|
|
|
|
|
[Parameter]
|
|
|
|
|
public RenderFragment ChildContent { get; set; }
|
|
|
|
|
|
|
|
|
|
private List<string> _targetKeys;
|
|
|
|
|
|
|
|
|
|
private bool _leftCheckAllState = false;
|
|
|
|
|
private bool _leftCheckAllIndeterminate = false;
|
|
|
|
|
private bool _rightCheckAllState = false;
|
|
|
|
|
private bool _rightCheckAllIndeterminate = false;
|
|
|
|
|
|
2020-10-24 13:39:02 +08:00
|
|
|
|
private string _leftCountText = string.Empty;
|
|
|
|
|
private string _rightCountText = string.Empty;
|
2020-05-26 15:21:47 +08:00
|
|
|
|
|
|
|
|
|
private bool _leftButtonDisabled = true;
|
|
|
|
|
private bool _rightButtonDisabled = true;
|
|
|
|
|
|
|
|
|
|
private IEnumerable<TransferItem> _leftDataSource;
|
|
|
|
|
private IEnumerable<TransferItem> _rightDataSource;
|
|
|
|
|
|
|
|
|
|
private List<string> _sourceSelectedKeys;
|
|
|
|
|
private List<string> _targetSelectedKeys;
|
|
|
|
|
|
2020-10-24 13:39:02 +08:00
|
|
|
|
private string _leftFilterValue = string.Empty;
|
|
|
|
|
private string _rightFilterValue = string.Empty;
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
protected override void OnInitialized()
|
|
|
|
|
{
|
2020-10-24 13:39:02 +08:00
|
|
|
|
ClassMapper.Add(PrefixName);
|
2020-05-26 15:21:47 +08:00
|
|
|
|
|
|
|
|
|
_targetKeys = TargetKeys.ToList();
|
|
|
|
|
var selectedKeys = SelectedKeys.ToList();
|
|
|
|
|
_sourceSelectedKeys = selectedKeys.Where(key => !_targetKeys.Contains(key)).ToList();
|
|
|
|
|
_targetSelectedKeys = selectedKeys.Where(key => _targetKeys.Contains(key)).ToList();
|
2020-10-24 13:39:02 +08:00
|
|
|
|
var count = _sourceSelectedKeys.Count;
|
2020-05-26 15:21:47 +08:00
|
|
|
|
|
|
|
|
|
InitData();
|
|
|
|
|
|
|
|
|
|
MathTitleCount();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitData()
|
|
|
|
|
{
|
|
|
|
|
_leftDataSource = DataSource.Where(a => !_targetKeys.Contains(a.Key));
|
|
|
|
|
_rightDataSource = DataSource.Where(a => _targetKeys.Contains(a.Key));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void MathTitleCount()
|
|
|
|
|
{
|
|
|
|
|
_rightButtonDisabled = _sourceSelectedKeys.Count == 0;
|
|
|
|
|
_leftButtonDisabled = _targetSelectedKeys.Count == 0;
|
2020-10-24 13:39:02 +08:00
|
|
|
|
|
|
|
|
|
var leftSuffix = _leftDataSource.Count() == 1 ? Locale.ItemUnit : Locale.ItemsUnit;
|
|
|
|
|
var rightSuffix = _rightDataSource.Count() == 1 ? Locale.ItemUnit : Locale.ItemsUnit;
|
|
|
|
|
|
|
|
|
|
var leftCount = _sourceSelectedKeys.Count == 0 ? $"{_leftDataSource.Count()}" : $"{_sourceSelectedKeys.Count}/{_leftDataSource.Count()}";
|
|
|
|
|
var rightCount = _targetSelectedKeys.Count == 0 ? $"{_rightDataSource.Count()}" : $"{_targetSelectedKeys.Count}/{_rightDataSource.Count()}";
|
|
|
|
|
|
|
|
|
|
_leftCountText = $"{leftCount} {leftSuffix}";
|
|
|
|
|
_rightCountText = $"{rightCount} {rightSuffix}";
|
2020-05-26 15:21:47 +08:00
|
|
|
|
|
|
|
|
|
CheckAllState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task SelectItem(bool isCheck, string direction, string key)
|
|
|
|
|
{
|
|
|
|
|
var holder = direction == TransferDirection.Left ? _sourceSelectedKeys : _targetSelectedKeys;
|
2020-10-24 13:39:02 +08:00
|
|
|
|
var index = Array.IndexOf(holder.ToArray(), key);
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
if (index > -1)
|
|
|
|
|
{
|
|
|
|
|
holder.RemoveAt(index);
|
|
|
|
|
}
|
|
|
|
|
if (isCheck)
|
|
|
|
|
holder.Add(key);
|
|
|
|
|
|
|
|
|
|
HandleSelect(direction, holder);
|
|
|
|
|
|
|
|
|
|
MathTitleCount();
|
|
|
|
|
|
|
|
|
|
if (OnSelectChange.HasDelegate)
|
|
|
|
|
{
|
|
|
|
|
await OnSelectChange.InvokeAsync(new TransferSelectChangeArgs(_sourceSelectedKeys.ToArray(), _targetSelectedKeys.ToArray()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task SelectAll(bool isCheck, string direction)
|
|
|
|
|
{
|
|
|
|
|
var list = _leftDataSource;
|
|
|
|
|
if (direction == TransferDirection.Right)
|
|
|
|
|
{
|
|
|
|
|
list = _rightDataSource;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var holder = isCheck ? list.Where(a => !a.Disabled).Select(a => a.Key).ToList() : new List<string>(list.Count());
|
2020-10-24 13:39:02 +08:00
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
HandleSelect(direction, holder);
|
|
|
|
|
|
|
|
|
|
MathTitleCount();
|
2020-10-24 13:39:02 +08:00
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
if (OnSelectChange.HasDelegate)
|
|
|
|
|
{
|
|
|
|
|
await OnSelectChange.InvokeAsync(new TransferSelectChangeArgs(_sourceSelectedKeys.ToArray(), _targetSelectedKeys.ToArray()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HandleSelect(string direction, List<string> keys)
|
|
|
|
|
{
|
|
|
|
|
if (direction == TransferDirection.Left)
|
2020-10-24 13:39:02 +08:00
|
|
|
|
{
|
2020-05-26 15:21:47 +08:00
|
|
|
|
_sourceSelectedKeys = keys;
|
2020-10-24 13:39:02 +08:00
|
|
|
|
}
|
2020-05-26 15:21:47 +08:00
|
|
|
|
else
|
2020-10-24 13:39:02 +08:00
|
|
|
|
{
|
2020-05-26 15:21:47 +08:00
|
|
|
|
_targetSelectedKeys = keys;
|
2020-10-24 13:39:02 +08:00
|
|
|
|
}
|
2020-05-26 15:21:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task MoveItem(MouseEventArgs e, string direction)
|
|
|
|
|
{
|
|
|
|
|
var moveKeys = direction == TransferDirection.Right ? _sourceSelectedKeys : _targetSelectedKeys;
|
2020-10-24 13:39:02 +08:00
|
|
|
|
|
|
|
|
|
if (direction == TransferDirection.Left)
|
2020-05-26 15:21:47 +08:00
|
|
|
|
{
|
2020-10-24 13:39:02 +08:00
|
|
|
|
_targetKeys.RemoveAll(key => moveKeys.Contains(key));
|
2020-05-26 15:21:47 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-10-24 13:39:02 +08:00
|
|
|
|
_targetKeys.AddRange(moveKeys);
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InitData();
|
|
|
|
|
|
2020-10-24 13:39:02 +08:00
|
|
|
|
var oppositeDirection = direction == TransferDirection.Right ? TransferDirection.Left : TransferDirection.Right;
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
HandleSelect(oppositeDirection, new List<string>());
|
|
|
|
|
|
2020-10-24 13:39:02 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(_leftFilterValue))
|
|
|
|
|
{
|
|
|
|
|
await HandleSearch(new ChangeEventArgs() { Value = _leftFilterValue }, TransferDirection.Left, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrEmpty(_rightFilterValue))
|
|
|
|
|
{
|
|
|
|
|
await HandleSearch(new ChangeEventArgs() { Value = _rightFilterValue }, TransferDirection.Right, false);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
MathTitleCount();
|
2020-10-24 13:39:02 +08:00
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
if (OnChange.HasDelegate)
|
|
|
|
|
{
|
|
|
|
|
await OnChange.InvokeAsync(new TransferChangeArgs(_targetKeys.ToArray(), direction, moveKeys.ToArray()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CheckAllState()
|
|
|
|
|
{
|
2020-10-24 13:39:02 +08:00
|
|
|
|
if (_leftDataSource.Any(a => !a.Disabled))
|
|
|
|
|
{
|
|
|
|
|
_leftCheckAllState = _sourceSelectedKeys.Count == _leftDataSource.Count(a => !a.Disabled);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_leftCheckAllState = false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
_leftCheckAllIndeterminate = !_leftCheckAllState && _sourceSelectedKeys.Count > 0;
|
|
|
|
|
|
2020-10-24 13:39:02 +08:00
|
|
|
|
if (_rightDataSource.Any(a => !a.Disabled))
|
|
|
|
|
{
|
|
|
|
|
_rightCheckAllState = _targetSelectedKeys.Count == _rightDataSource.Count(a => !a.Disabled);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_rightCheckAllState = false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 15:21:47 +08:00
|
|
|
|
_rightCheckAllIndeterminate = !_rightCheckAllState && _targetSelectedKeys.Count > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task HandleScroll(string direction, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (OnScroll.HasDelegate)
|
|
|
|
|
{
|
|
|
|
|
await OnScroll.InvokeAsync(new TransferScrollArgs(direction, e));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-24 13:39:02 +08:00
|
|
|
|
private async Task HandleSearch(ChangeEventArgs e, string direction, bool mathTileCount = true)
|
2020-05-26 15:21:47 +08:00
|
|
|
|
{
|
|
|
|
|
if (direction == TransferDirection.Left)
|
2020-10-24 13:39:02 +08:00
|
|
|
|
{
|
|
|
|
|
_leftFilterValue = e.Value.ToString();
|
|
|
|
|
_leftDataSource = DataSource.Where(a => !_targetKeys.Contains(a.Key) && a.Title.Contains(_leftFilterValue, StringComparison.InvariantCultureIgnoreCase)).ToList();
|
|
|
|
|
}
|
2020-05-26 15:21:47 +08:00
|
|
|
|
else
|
2020-10-24 13:39:02 +08:00
|
|
|
|
{
|
|
|
|
|
_rightFilterValue = e.Value.ToString();
|
|
|
|
|
_rightDataSource = DataSource.Where(a => _targetKeys.Contains(a.Key) && a.Title.Contains(_rightFilterValue, StringComparison.InvariantCultureIgnoreCase)).ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mathTileCount)
|
|
|
|
|
MathTitleCount();
|
2020-05-26 15:21:47 +08:00
|
|
|
|
|
|
|
|
|
if (OnSearch.HasDelegate)
|
|
|
|
|
{
|
|
|
|
|
await OnSearch.InvokeAsync(new TransferSearchArgs(direction, e.Value.ToString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-24 13:39:02 +08:00
|
|
|
|
|
|
|
|
|
private async Task ClearFilterValueAsync(string direction)
|
|
|
|
|
{
|
|
|
|
|
if (direction == TransferDirection.Left)
|
|
|
|
|
{
|
|
|
|
|
_leftFilterValue = string.Empty;
|
|
|
|
|
await HandleSearch(new ChangeEventArgs() { Value = string.Empty }, direction);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_rightFilterValue = string.Empty;
|
|
|
|
|
await HandleSearch(new ChangeEventArgs() { Value = string.Empty }, direction);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-26 15:21:47 +08:00
|
|
|
|
}
|
|
|
|
|
}
|