ant-design-blazor/components/menu/Menu.razor.cs
James Yeung 4d2c77fec7 refactor: dropdown and menu (#126)
* feat: add mock browser

* docs: add mock browser

* docs: rename menu

* fix: style for submenu

* docs: add two menu demo

* fix: some errors

* fix(module:menu): openkeys

* docs: add switch-mode demo for menu

* docs(module:menu): finish demos

* docs(module: menu): add router demo

* docs: add new demos (#111)

* feat(module: datepicker): remove ant prefix

* feat(module: dropdown): remove ant prefix

* feat(module: empty): remove ant prefix

* feat(module: timepicker): remove ant prefix

* docs(module: datepicker): add new demos

* docs(module: dropdown): add new demos

* docs(module: empty): add new demos

* docs(module: timepicker): add new demos

* docs: remove old demo

Co-authored-by: 钟迪龙 <mutouzdl@hotmail.com>

* refactor(module: dropdown): add overlay (#122)

* feat(module: dropdown): support left/right popup

* feat(module: submenu): use dropdown to popup

* feat: add overlay and trigger class(not complete yet)

* feat: add OverlayTrigger.cs

* feat: submenu support dropdown

* feat(module: overlay): prevent hide when child is showing

* fix(module: menu): prefixCls error

* feat(module: overlay-trigger): change function to virtual

* feat(module: dropdown): remove unuse class

* feat(module: sub-menu): set IsOpen to Visible

* refactor: change namespace

* refactor: use smartEnum

* fix: menu json

* fix: submenu open state

Co-authored-by: 笨木头 <musicvs@163.com>
Co-authored-by: 钟迪龙 <mutouzdl@hotmail.com>
2020-05-18 14:46:42 +08:00

243 lines
6.3 KiB
C#

using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
namespace AntBlazor
{
public partial class Menu : AntDomComponentBase
{
[CascadingParameter(Name = "PrefixCls")]
public string PrefixCls { get; set; } = "ant-menu";
[CascadingParameter]
public AntSider Parent { get; set; }
[Parameter]
public MenuTheme Theme { get; set; } = MenuTheme.Light;
[Parameter]
public MenuMode Mode { get; set; } = MenuMode.Vertical;
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public EventCallback<SubMenu> OnSubmenuClicked { get; set; }
[Parameter]
public EventCallback<MenuItem> OnMenuItemClicked { get; set; }
[Parameter]
public bool Accordion { get; set; }
[Parameter]
public bool Selectable { get; set; } = true;
[Parameter]
public bool InlineCollapsed { get; set; }
[Parameter]
public IEnumerable<string> DefaultSelectedKeys { get; set; } = new List<string>();
[Parameter]
public IEnumerable<string> DefaultOpenKeys { get; set; } = new List<string>();
[Parameter]
public string[] OpenKeys
{
get => _openKeys ?? Array.Empty<string>();
set
{
_openKeys = value;
HandleOpenKeySet();
}
}
[Parameter]
public EventCallback<string[]> OpenKeysChanged { get; set; }
[Parameter]
public EventCallback<string[]> OnOpenChange { get; set; }
[Parameter]
public string[] SelectedKeys
{
get => _selectedKeys ?? Array.Empty<string>();
set
{
_selectedKeys = value;
}
}
[Parameter]
public EventCallback<string[]> SelectedKeysChanged { get; set; }
internal MenuMode InternalMode { get; private set; }
private bool _collapsed;
private string[] _openKeys;
private string[] _selectedKeys;
public List<SubMenu> Submenus { get; set; } = new List<SubMenu>();
public List<MenuItem> MenuItems { get; set; } = new List<MenuItem>();
public void SelectItem(MenuItem item)
{
if (item == null)
{
return;
}
foreach (MenuItem menuitem in MenuItems.Where(x => x != item))
{
menuitem.Deselect();
}
if (!item.IsSelected)
{
item.Select();
}
else
{
item.Deselect();
}
StateHasChanged();
if (OnMenuItemClicked.HasDelegate)
OnMenuItemClicked.InvokeAsync(item);
_selectedKeys = MenuItems.Where(x => x.IsSelected).Select(x => x.Key).ToArray();
if (SelectedKeysChanged.HasDelegate)
SelectedKeysChanged.InvokeAsync(_selectedKeys);
}
public void SelectSubmenu(SubMenu menu)
{
if (menu == null)
{
return;
}
if (Accordion)
{
foreach (SubMenu item in Submenus.Where(x => x != menu && x != menu.Parent))
{
item.Close();
}
}
if (menu.IsOpen)
{
menu.Close();
}
else
{
menu.Open();
}
if (OnSubmenuClicked.HasDelegate)
OnSubmenuClicked.InvokeAsync(menu);
var openKeys = Submenus.Where(x => x.IsOpen).Select(x => x.Key).ToArray();
HandleOpenChange(openKeys);
StateHasChanged();
}
private void SetClass()
{
ClassMapper
.Clear()
.Add(PrefixCls)
.Add($"{PrefixCls}-root")
.Add($"{PrefixCls}-{Theme}")
.Add($"{PrefixCls}-{InternalMode}")
.If($"{PrefixCls}-inline-collapsed", () => _collapsed)
.If($"{PrefixCls}-unselectable", () => !Selectable);
}
protected override void OnInitialized()
{
base.OnInitialized();
if (InternalMode != MenuMode.Inline && _collapsed)
throw new ArgumentException($"{nameof(Menu)} in the {Mode} mode cannot be {nameof(InlineCollapsed)}");
InternalMode = Mode;
if (Parent != null)
{
Parent.OnCollapsed += Update;
}
SetClass();
}
protected override void OnParametersSet()
{
base.OnParametersSet();
if (Parent == null)
{
this._collapsed = InlineCollapsed;
}
Update(_collapsed);
SetClass();
}
public void Update(bool collapsed)
{
this._collapsed = collapsed;
if (collapsed)
{
InternalMode = MenuMode.Vertical;
foreach (SubMenu item in Submenus)
{
item.Close();
}
HandleOpenChange(Array.Empty<string>());
}
else
{
InternalMode = Mode;
}
}
private void HandleOpenChange(string[] openKeys)
{
this._openKeys = openKeys;
if (OnOpenChange.HasDelegate)
OnOpenChange.InvokeAsync(openKeys);
if (OpenKeysChanged.HasDelegate)
OpenKeysChanged.InvokeAsync(openKeys);
}
private void HandleOpenKeySet()
{
foreach (SubMenu item in Submenus.Where(x => x.Key.IsIn(this.OpenKeys)))
{
item.Open();
}
foreach (SubMenu item in Submenus.Where(x => !x.Key.IsIn(this.OpenKeys)))
{
item.Close();
}
StateHasChanged();
}
protected override void Dispose(bool disposing)
{
if (Parent != null)
{
Parent.OnCollapsed -= Update;
}
base.Dispose(disposing);
}
}
}