mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-07-08 18:16:08 +00:00
695 lines
26 KiB
C#
695 lines
26 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.AspNetCore.Components.Forms;
|
|
using Radzen;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Radzen.Blazor
|
|
{
|
|
/// <summary>
|
|
/// RadzenPickList component.
|
|
/// </summary>
|
|
[UnconditionalSuppressMessage(TrimMessages.Trimming, TrimMessages.IL2026, Justification = TrimMessages.DataTypePreserved)]
|
|
public partial class RadzenPickList<TItem> : RadzenComponent
|
|
{
|
|
/// <summary>
|
|
/// Gets or sets the edit context.
|
|
/// </summary>
|
|
[CascadingParameter]
|
|
public EditContext? EditContext { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source expression used to create the FieldIdentifier for source validation.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Expression<Func<IEnumerable<TItem>?>>? SourceExpression { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target expression used to create the FieldIdentifier for target validation.
|
|
/// </summary>
|
|
[Parameter]
|
|
public Expression<Func<IEnumerable<TItem>?>>? TargetExpression { get; set; }
|
|
|
|
FieldIdentifier? sourceFieldIdentifier;
|
|
FieldIdentifier? targetFieldIdentifier;
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether it is allowed to move all items.
|
|
/// </summary>
|
|
/// <value><c>true</c> if c allowed to move all items; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool AllowMoveAll { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether it is allowed to move all items from source to target.
|
|
/// </summary>
|
|
/// <value><c>true</c> if c allowed to move all items from source to target; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool AllowMoveAllSourceToTarget { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether it is allowed to move all items from target to source.
|
|
/// </summary>
|
|
/// <value><c>true</c> if c allowed to move all items from target to source; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool AllowMoveAllTargetToSource { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether to move all or only avaialable after filter items.
|
|
/// </summary>
|
|
/// <value><c>true</c> if c allowed to move filtered items only; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool MoveFilteredItemsOnlyOnMoveAll { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether multiple selection is allowed.
|
|
/// </summary>
|
|
/// <value><c>true</c> if multiple selection is allowed; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool Multiple { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether selecting all items is allowed.
|
|
/// </summary>
|
|
/// <value><c>true</c> if selecting all items is allowed; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool AllowSelectAll { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether virtualization is enabled for the source and target listboxes.
|
|
/// </summary>
|
|
/// <value><c>true</c> if virtualization is enabled; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool AllowVirtualization { get; set; }
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether component is disabled.
|
|
/// </summary>
|
|
/// <value><c>true</c> if component is disabled; otherwise, <c>false</c>.</value>
|
|
[Parameter]
|
|
public bool Disabled { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source header
|
|
/// </summary>
|
|
/// <value>The source header.</value>
|
|
[Parameter]
|
|
public RenderFragment? SourceHeader { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target header
|
|
/// </summary>
|
|
/// <value>The target header.</value>
|
|
[Parameter]
|
|
public RenderFragment? TargetHeader { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the common placeholder
|
|
/// </summary>
|
|
/// <value>The common placeholder.</value>
|
|
[Parameter]
|
|
public string? Placeholder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source placeholder
|
|
/// </summary>
|
|
/// <value>The source placeholder.</value>
|
|
[Parameter]
|
|
public string? SourcePlaceholder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target placeholder
|
|
/// </summary>
|
|
/// <value>The target placeholder.</value>
|
|
[Parameter]
|
|
public string? TargetPlaceholder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the text property
|
|
/// </summary>
|
|
/// <value>The text property.</value>
|
|
[Parameter]
|
|
public string? TextProperty { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value property
|
|
/// </summary>
|
|
/// <value>The value property.</value>
|
|
[Parameter]
|
|
public string? ValueProperty { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the disabled property
|
|
/// </summary>
|
|
/// <value>The disabled property.</value>
|
|
[Parameter]
|
|
public string? DisabledProperty { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the template.
|
|
/// </summary>
|
|
/// <value>The template.</value>
|
|
[Parameter]
|
|
public RenderFragment<TItem>? Template { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source template. Overrides <see cref="Template"/>.
|
|
/// </summary>
|
|
/// <value>The source template.</value>
|
|
[Parameter]
|
|
public RenderFragment<TItem>? SourceTemplate { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target template. Overrides <see cref="Template"/>.
|
|
/// </summary>
|
|
/// <value>The target template.</value>
|
|
[Parameter]
|
|
public RenderFragment<TItem>? TargetTemplate { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the select all text.
|
|
/// </summary>
|
|
/// <value>The select all text.</value>
|
|
[Parameter]
|
|
public string? SelectAllText { get; set; }
|
|
|
|
private string? emptyText;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the empty text shown when a list has no items.
|
|
/// </summary>
|
|
/// <value>The empty text.</value>
|
|
[Parameter]
|
|
public string EmptyText { get => emptyText ?? Localize(nameof(RadzenStrings.PickList_EmptyText)); set => emptyText = value; }
|
|
|
|
private string? sourceAriaLabel;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the aria-label of the source list. Ignored when <see cref="SourceHeader"/> is rendered - the source list is labelled by the header instead.
|
|
/// </summary>
|
|
/// <value>The source list aria-label.</value>
|
|
[Parameter]
|
|
public string SourceAriaLabel { get => sourceAriaLabel ?? Localize(nameof(RadzenStrings.PickList_SourceAriaLabel)); set => sourceAriaLabel = value; }
|
|
|
|
private string? targetAriaLabel;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the aria-label of the target list. Ignored when <see cref="TargetHeader"/> is rendered - the target list is labelled by the header instead.
|
|
/// </summary>
|
|
/// <value>The target list aria-label.</value>
|
|
[Parameter]
|
|
public string TargetAriaLabel { get => targetAriaLabel ?? Localize(nameof(RadzenStrings.PickList_TargetAriaLabel)); set => targetAriaLabel = value; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the empty text shown when the source list has no items. Overrides <see cref="EmptyText"/>.
|
|
/// </summary>
|
|
/// <value>The source empty text.</value>
|
|
[Parameter]
|
|
public string? SourceEmptyText { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the empty text shown when the target list has no items. Overrides <see cref="EmptyText"/>.
|
|
/// </summary>
|
|
/// <value>The target empty text.</value>
|
|
[Parameter]
|
|
public string? TargetEmptyText { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the empty template shown when a list has no items.
|
|
/// </summary>
|
|
/// <value>The empty template.</value>
|
|
[Parameter]
|
|
public RenderFragment? EmptyTemplate { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the empty template shown when the source list has no items. Overrides <see cref="EmptyTemplate"/>.
|
|
/// </summary>
|
|
/// <value>The source empty template.</value>
|
|
[Parameter]
|
|
public RenderFragment? SourceEmptyTemplate { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the empty template shown when the target list has no items. Overrides <see cref="EmptyTemplate"/>.
|
|
/// </summary>
|
|
/// <value>The target empty template.</value>
|
|
[Parameter]
|
|
public RenderFragment? TargetEmptyTemplate { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the row render callback. Use it to set row attributes.
|
|
/// </summary>
|
|
/// <value>The row render callback.</value>
|
|
[Parameter]
|
|
public Action<PickListItemRenderEventArgs<TItem>>? ItemRender { get; set; }
|
|
|
|
void OnSourceItemRender(ListBoxItemRenderEventArgs<object?> args)
|
|
{
|
|
if (ItemRender != null)
|
|
{
|
|
var newArgs = new PickListItemRenderEventArgs<TItem>();
|
|
newArgs.Item = args.Item != null ? (TItem)args.Item : default(TItem);
|
|
ItemRender(newArgs);
|
|
newArgs.Attributes.ToList().ForEach(k => args.Attributes.Add(k.Key, k.Value));
|
|
args.Visible = newArgs.Visible;
|
|
args.Disabled = newArgs.Disabled;
|
|
}
|
|
}
|
|
|
|
void OnTargetItemRender(ListBoxItemRenderEventArgs<object?> args)
|
|
{
|
|
if (ItemRender != null)
|
|
{
|
|
var newArgs = new PickListItemRenderEventArgs<TItem>();
|
|
newArgs.Item = args.Item != null ? (TItem)args.Item : default(TItem);
|
|
ItemRender(newArgs);
|
|
newArgs.Attributes.ToList().ForEach(k => args.Attributes.Add(k.Key, k.Value));
|
|
args.Visible = newArgs.Visible;
|
|
args.Disabled = newArgs.Disabled;
|
|
}
|
|
}
|
|
|
|
private RenderFragment<dynamic>? SourceListBoxTemplate
|
|
{
|
|
get
|
|
{
|
|
if (SourceTemplate != null)
|
|
{
|
|
return item => SourceTemplate(item);
|
|
}
|
|
|
|
if (Template != null)
|
|
{
|
|
return item => Template(item);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private RenderFragment<dynamic>? TargetListBoxTemplate
|
|
{
|
|
get
|
|
{
|
|
if (TargetTemplate != null)
|
|
{
|
|
return item => TargetTemplate(item);
|
|
}
|
|
|
|
if (Template != null)
|
|
{
|
|
return item => Template(item);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets value if filtering is allowed.
|
|
/// </summary>
|
|
/// <value>The allow filtering value.</value>
|
|
[Parameter]
|
|
public bool AllowFiltering { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets value if headers are shown.
|
|
/// </summary>
|
|
/// <value>If headers are shown value.</value>
|
|
[Parameter]
|
|
public bool ShowHeader { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the buttons spacing
|
|
/// </summary>
|
|
/// <value>The buttons spacing.</value>
|
|
[Parameter]
|
|
public string? ButtonGap { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the orientation
|
|
/// </summary>
|
|
/// <value>The orientation.</value>
|
|
[Parameter]
|
|
public Orientation Orientation { get; set; } = Orientation.Horizontal;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the buttons style
|
|
/// </summary>
|
|
/// <value>The buttons style.</value>
|
|
[Parameter]
|
|
public JustifyContent ButtonJustifyContent { get; set; } = JustifyContent.Center;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the buttons style
|
|
/// </summary>
|
|
/// <value>The buttons style.</value>
|
|
[Parameter]
|
|
public ButtonStyle ButtonStyle { get; set; } = ButtonStyle.Primary;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the design variant of the buttons.
|
|
/// </summary>
|
|
/// <value>The variant of the buttons.</value>
|
|
[Parameter]
|
|
public Variant ButtonVariant { get; set; } = Variant.Text;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the color shade of the buttons.
|
|
/// </summary>
|
|
/// <value>The color shade of the buttons.</value>
|
|
[Parameter]
|
|
public Shade ButtonShade { get; set; } = Shade.Default;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the buttons size.
|
|
/// </summary>
|
|
/// <value>The buttons size.</value>
|
|
[Parameter]
|
|
public ButtonSize ButtonSize { get; set; } = ButtonSize.Medium;
|
|
|
|
private string? sourceToTargetTitle;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source to target title
|
|
/// </summary>
|
|
/// <value>The source to target title.</value>
|
|
[Parameter]
|
|
public string SourceToTargetTitle { get => sourceToTargetTitle ?? Localize(nameof(RadzenStrings.PickList_SourceToTargetTitle)); set => sourceToTargetTitle = value; }
|
|
|
|
private string? selectedSourceToTargetTitle;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the selected source to target title
|
|
/// </summary>
|
|
/// <value>The selected source to target title.</value>
|
|
[Parameter]
|
|
public string SelectedSourceToTargetTitle { get => selectedSourceToTargetTitle ?? Localize(nameof(RadzenStrings.PickList_SelectedSourceToTargetTitle)); set => selectedSourceToTargetTitle = value; }
|
|
|
|
private string? targetToSourceTitle;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target to source title
|
|
/// </summary>
|
|
/// <value>The target to source title.</value>
|
|
[Parameter]
|
|
public string TargetToSourceTitle { get => targetToSourceTitle ?? Localize(nameof(RadzenStrings.PickList_TargetToSourceTitle)); set => targetToSourceTitle = value; }
|
|
|
|
private string? selectedTargetToSourceTitle;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the selected target to source title
|
|
/// </summary>
|
|
/// <value>The selected target to source title.</value>
|
|
[Parameter]
|
|
public string SelectedTargetToSourceTitle { get => selectedTargetToSourceTitle ?? Localize(nameof(RadzenStrings.PickList_SelectedTargetToSourceTitle)); set => selectedTargetToSourceTitle = value; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source to target icon
|
|
/// </summary>
|
|
/// <value>The source to target icon.</value>
|
|
[Parameter]
|
|
public string SourceToTargetIcon { get; set; } = "keyboard_double_arrow_right";
|
|
|
|
/// <summary>
|
|
/// Gets or sets the selected source to target icon
|
|
/// </summary>
|
|
/// <value>The selected source to target icon.</value>
|
|
[Parameter]
|
|
public string SelectedSourceToTargetIcon { get; set; } = "keyboard_arrow_right";
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target to source icon
|
|
/// </summary>
|
|
/// <value>The target to source icon.</value>
|
|
[Parameter]
|
|
public string TargetToSourceIcon { get; set; } = "keyboard_double_arrow_left";
|
|
|
|
/// <summary>
|
|
/// Gets or sets the selected target to source icon
|
|
/// </summary>
|
|
/// <value>The selected target to source icon.</value>
|
|
[Parameter]
|
|
public string SelectedTargetToSourceIcon { get; set; } = "keyboard_arrow_left";
|
|
|
|
/// <summary>
|
|
/// Gets the final CSS style rendered by the component. Combines it with a <c>style</c> custom attribute.
|
|
/// </summary>
|
|
protected string? GetStyle()
|
|
{
|
|
if (Attributes != null && Attributes.TryGetValue("style", out var style) && !string.IsNullOrEmpty(Convert.ToString(@style, CultureInfo.InvariantCulture)))
|
|
{
|
|
return $"{Style} {@style}";
|
|
}
|
|
|
|
return Style;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override string GetComponentCssClass()
|
|
{
|
|
return "rz-picklist";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source collection.
|
|
/// </summary>
|
|
/// <value>The source collection.</value>
|
|
[Parameter]
|
|
public IEnumerable<TItem>? Source { get; set; }
|
|
|
|
IEnumerable<TItem>? source;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the source changed.
|
|
/// </summary>
|
|
/// <value>The source changed.</value>
|
|
[Parameter]
|
|
public EventCallback<IEnumerable<TItem>> SourceChanged { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target collection.
|
|
/// </summary>
|
|
/// <value>The target collection.</value>
|
|
[Parameter]
|
|
public IEnumerable<TItem>? Target { get; set; }
|
|
|
|
IEnumerable<TItem>? target;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the target changed.
|
|
/// </summary>
|
|
/// <value>The target changed.</value>
|
|
[Parameter]
|
|
public EventCallback<IEnumerable<TItem>> TargetChanged { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the callback that is invoked when the selected source items change.
|
|
/// </summary>
|
|
/// <value>The selected source items changed callback.</value>
|
|
[Parameter]
|
|
public EventCallback<IEnumerable<TItem>> SelectedSourceChanged { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the callback that is invoked when the selected target items change.
|
|
/// </summary>
|
|
/// <value>The selected target items changed callback.</value>
|
|
[Parameter]
|
|
public EventCallback<IEnumerable<TItem>> SelectedTargetChanged { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the callback that is invoked when items are moved between the source and target collections.
|
|
/// Fires after <see cref="SourceChanged"/> and <see cref="TargetChanged"/>, so the bound collections already reflect the move.
|
|
/// </summary>
|
|
/// <value>The move callback.</value>
|
|
[Parameter]
|
|
public EventCallback<PickListMoveEventArgs<TItem>> Move { get; set; }
|
|
|
|
object? selectedSourceItems;
|
|
object? selectedTargetItems;
|
|
|
|
async Task OnSelectedSourceItemsChanged(object value)
|
|
{
|
|
selectedSourceItems = value;
|
|
await SelectedSourceChanged.InvokeAsync(GetSelectedSources());
|
|
}
|
|
|
|
async Task OnSelectedTargetItemsChanged(object value)
|
|
{
|
|
selectedTargetItems = value;
|
|
await SelectedTargetChanged.InvokeAsync(GetSelectedTargets());
|
|
}
|
|
|
|
string? sourceSearchText;
|
|
string? targetSearchText;
|
|
|
|
/// <summary>
|
|
/// Set parameters as an asynchronous operation.
|
|
/// </summary>
|
|
/// <param name="parameters">The parameters.</param>
|
|
/// <returns>A Task representing the asynchronous operation.</returns>
|
|
public override async Task SetParametersAsync(ParameterView parameters)
|
|
{
|
|
var sourceChanged = parameters.DidParameterChange(nameof(Source), Source);
|
|
if (sourceChanged)
|
|
{
|
|
source = parameters.GetValueOrDefault<IEnumerable<TItem>>(nameof(Source));
|
|
}
|
|
|
|
var targetChanged = parameters.DidParameterChange(nameof(Target), Target);
|
|
if (targetChanged)
|
|
{
|
|
target = parameters.GetValueOrDefault<IEnumerable<TItem>>(nameof(Target));
|
|
}
|
|
|
|
if (parameters.DidParameterChange(nameof(Multiple), Multiple))
|
|
{
|
|
selectedSourceItems = null;
|
|
selectedTargetItems = null;
|
|
}
|
|
|
|
await base.SetParametersAsync(parameters);
|
|
|
|
if (EditContext != null)
|
|
{
|
|
if (SourceExpression != null && sourceFieldIdentifier == null)
|
|
{
|
|
sourceFieldIdentifier = FieldIdentifier.Create(SourceExpression);
|
|
}
|
|
|
|
if (TargetExpression != null && targetFieldIdentifier == null)
|
|
{
|
|
targetFieldIdentifier = FieldIdentifier.Create(TargetExpression);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a collection of TItem that are selected in the source list.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public IEnumerable<TItem> GetSelectedSources() => GetSelectedItems(selectedSourceItems, source);
|
|
|
|
/// <summary>
|
|
/// Returns a collection of TItem that are selected in the target list.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public IEnumerable<TItem> GetSelectedTargets() => GetSelectedItems(selectedTargetItems, target);
|
|
|
|
IEnumerable<TItem> GetSelectedItems(object? selectedItems, IEnumerable<TItem>? data)
|
|
{
|
|
if (selectedItems == null)
|
|
{
|
|
return Enumerable.Empty<TItem>();
|
|
}
|
|
|
|
var selected = Multiple
|
|
? (selectedItems as IEnumerable)?.Cast<object?>().ToList() ?? new List<object?>()
|
|
: new List<object?> { selectedItems };
|
|
|
|
if (selected.Count > 0 && selected.All(o => o is TItem))
|
|
{
|
|
return selected.Cast<TItem>();
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(ValueProperty) && data != null)
|
|
{
|
|
var selectedValues = new HashSet<object?>(selected);
|
|
return data.Where(item => selectedValues.Contains(PropertyAccess.GetValue(item, ValueProperty)));
|
|
}
|
|
|
|
return Enumerable.Empty<TItem>();
|
|
}
|
|
|
|
RadzenListBox<object>? sourceListBox;
|
|
RadzenListBox<object>? targetListBox;
|
|
private async Task Update(bool sourceToTarget, IEnumerable<TItem>? items)
|
|
{
|
|
IEnumerable<TItem> movedItems;
|
|
|
|
if (sourceToTarget)
|
|
{
|
|
if (items != null)
|
|
{
|
|
movedItems = items as IList<TItem> ?? items.ToList();
|
|
target = (target ?? Enumerable.Empty<TItem>()).Concat(movedItems);
|
|
source = (source ?? Enumerable.Empty<TItem>()).Except(movedItems);
|
|
}
|
|
else
|
|
{
|
|
movedItems = (MoveFilteredItemsOnlyOnMoveAll ? sourceListBox?.GetView()?.Cast<TItem>() ?? Enumerable.Empty<TItem>() : source ?? Enumerable.Empty<TItem>()).ToList();
|
|
target = (target ?? Enumerable.Empty<TItem>()).Concat(movedItems);
|
|
source = MoveFilteredItemsOnlyOnMoveAll && source != null ? source.Except(movedItems) : null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (items != null)
|
|
{
|
|
movedItems = items as IList<TItem> ?? items.ToList();
|
|
source = (source ?? Enumerable.Empty<TItem>()).Concat(movedItems);
|
|
target = (target ?? Enumerable.Empty<TItem>()).Except(movedItems);
|
|
}
|
|
else
|
|
{
|
|
movedItems = (MoveFilteredItemsOnlyOnMoveAll ? targetListBox?.GetView()?.Cast<TItem>() ?? Enumerable.Empty<TItem>() : target ?? Enumerable.Empty<TItem>()).ToList();
|
|
source = (source ?? Enumerable.Empty<TItem>()).Concat(movedItems);
|
|
target = MoveFilteredItemsOnlyOnMoveAll && target != null ? target.Except(movedItems) : null;
|
|
}
|
|
}
|
|
|
|
source = source?.Any() == true ? source : null;
|
|
target = target?.Any() == true ? target : null;
|
|
|
|
await SourceChanged.InvokeAsync(source);
|
|
await TargetChanged.InvokeAsync(target);
|
|
|
|
if (Move.HasDelegate)
|
|
{
|
|
await Move.InvokeAsync(new PickListMoveEventArgs<TItem>
|
|
{
|
|
MoveDirectionToTarget = sourceToTarget,
|
|
Items = movedItems,
|
|
});
|
|
}
|
|
|
|
if (EditContext != null)
|
|
{
|
|
if (sourceFieldIdentifier.HasValue)
|
|
{
|
|
EditContext.NotifyFieldChanged(sourceFieldIdentifier.Value);
|
|
}
|
|
|
|
if (targetFieldIdentifier.HasValue)
|
|
{
|
|
EditContext.NotifyFieldChanged(targetFieldIdentifier.Value);
|
|
}
|
|
}
|
|
|
|
selectedSourceItems = null;
|
|
selectedTargetItems = null;
|
|
|
|
if (items == null && !MoveFilteredItemsOnlyOnMoveAll)
|
|
{
|
|
sourceSearchText = null;
|
|
targetSearchText = null;
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
|
|
private async Task SourceToTarget() => await Update(true, null);
|
|
|
|
private async Task SelectedSourceToTarget() => await Update(true, GetSelectedSources());
|
|
|
|
private async Task TargetToSource() => await Update(false, null);
|
|
|
|
private async Task SelectedTargetToSource() => await Update(false, GetSelectedTargets());
|
|
}
|
|
}
|