You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Connected.Components/Components/Select/SelectItem.razor.cs

155 lines
3.7 KiB

2 years ago
using Connected.Annotations;
using Connected.Utilities;
using Microsoft.AspNetCore.Components;
namespace Connected.Components;
/// <summary>
/// Represents an option of a select or multi-select. To be used inside MudSelect.
/// </summary>
public partial class SelectItem<T> : SelectItemBase, IDisposable
{
private String GetCssClasses() => new CssBuilder()
.AddClass(Class)
.Build();
private ISelect _parent;
internal string ItemId { get; } = "_" + Guid.NewGuid().ToString().Substring(0, 8);
/// <summary>
/// The parent select component
/// </summary>
[CascadingParameter]
internal ISelect IMudSelect
{
get => _parent;
set
{
_parent = value;
if (_parent == null)
return;
_parent.CheckGenericTypeMatch(this);
if (Select == null)
return;
bool isSelected = Select.Add(this);
if (_parent.MultiSelection)
{
Select.SelectionChangedFromOutside += OnUpdateSelectionStateFromOutside;
InvokeAsync(() => OnUpdateSelectionStateFromOutside(Select.SelectedValues));
}
else
{
IsSelected = isSelected;
}
}
}
private IShadowSelect _shadowParent;
private bool _isSelected;
[CascadingParameter]
internal IShadowSelect ParentShadow
{
get => _shadowParent;
set
{
_shadowParent = value;
((Select<T>)_shadowParent)?.RegisterShadowItem(this);
}
}
/// <summary>
/// Select items with HideContent==true are only there to register their RenderFragment with the select but
/// wont render and have no other purpose!
/// </summary>
[CascadingParameter(Name = "HideContent")]
internal bool HideContent { get; set; }
internal Select<T> Select => (Select<T>)IMudSelect;
private void OnUpdateSelectionStateFromOutside(IEnumerable<T> selection)
{
if (selection == null)
return;
var old_is_selected = IsSelected;
IsSelected = selection.Contains(Value);
if (old_is_selected != IsSelected)
InvokeAsync(StateHasChanged);
}
/// <summary>
/// A user-defined option that can be selected
/// </summary>
[Parameter]
[Category(CategoryTypes.FormComponent.Behavior)]
public T Value { get; set; }
/// <summary>
/// Mirrors the MultiSelection status of the parent select
/// </summary>
protected bool MultiSelection
{
get
{
if (Select == null)
return false;
return Select.MultiSelection;
}
}
/// <summary>
/// Selected state of the option. Only works if the parent is a mulit-select
/// </summary>
internal bool IsSelected
{
get => _isSelected;
set
{
_isSelected = value;
}
}
/// <summary>
/// The checkbox icon reflects the multi-select option's state
/// </summary>
protected string CheckBoxIcon
{
get
{
if (!MultiSelection)
return null;
return IsSelected ? Icons.Material.Filled.CheckBox : Icons.Material.Filled.CheckBoxOutlineBlank;
}
}
protected string DisplayString
{
get
{
var converter = Select?.Converter;
if (converter == null)
return $"{Value}";
return converter.Convert(Value);
2 years ago
}
}
private void OnClicked()
{
if (MultiSelection)
IsSelected = !IsSelected;
Select?.SelectOption(Value);
InvokeAsync(StateHasChanged);
}
public void Dispose()
{
try
{
Select?.Remove(this);
((Select<T>)_shadowParent)?.UnregisterShadowItem(this);
}
catch (Exception) { }
}
}