using System; using System.Linq; using System.Windows; using HandyControl.Data; namespace HandyControl.Controls; public class SideMenu : HeaderedSimpleItemsControl { private SideMenuItem _selectedItem; private SideMenuItem _selectedHeader; private bool _isItemSelected; public SideMenu() { AddHandler(SideMenuItem.SelectedEvent, new RoutedEventHandler(SideMenuItemSelected)); Loaded += (s, e) => Init(); } protected override void Refresh() { base.Refresh(); Init(); } private void Init() { if (ItemsHost == null) return; OnExpandModeChanged(ExpandMode); } private void SideMenuItemSelected(object sender, RoutedEventArgs e) { if (e.OriginalSource is SideMenuItem item) { if (item.Role == SideMenuItemRole.Item) { _isItemSelected = true; if (Equals(item, _selectedItem)) return; if (_selectedItem != null) { _selectedItem.IsSelected = false; } _selectedItem = item; _selectedItem.IsSelected = true; RaiseEvent(new FunctionEventArgs(SelectionChangedEvent, this) { Info = e.OriginalSource }); } else { if (!Equals(item, _selectedHeader)) { if (_selectedHeader != null) { if (ExpandMode == ExpandMode.Freedom && item.ItemsHost.IsVisible && !_isItemSelected) { item.IsSelected = false; SwitchPanelArea(item); return; } _selectedHeader.IsSelected = false; if (ExpandMode != ExpandMode.Freedom) { SwitchPanelArea(_selectedHeader); } } _selectedHeader = item; _selectedHeader.IsSelected = true; SwitchPanelArea(_selectedHeader); } else if (ExpandMode == ExpandMode.Freedom && !_isItemSelected) { _selectedHeader.IsSelected = false; SwitchPanelArea(_selectedHeader); _selectedHeader = null; } if (_isItemSelected) { _isItemSelected = false; } else if (_selectedHeader != null) { if (AutoSelect) { if (_selectedItem != null) { _selectedItem.IsSelected = false; _selectedItem = null; } _selectedHeader.SelectDefaultItem(); } _isItemSelected = false; } if (!item.HasItems) { RaiseEvent(new FunctionEventArgs(SelectionChangedEvent, this) { Info = e.OriginalSource }); } } } } private void SwitchPanelArea(SideMenuItem oldItem) { switch (ExpandMode) { case ExpandMode.ShowAll: return; case ExpandMode.ShowOne: case ExpandMode.Freedom: case ExpandMode.Accordion: oldItem.SwitchPanelArea(oldItem.IsSelected); break; } } protected override DependencyObject GetContainerForItemOverride() => new SideMenuItem(); protected override bool IsItemItsOwnContainerOverride(object item) => item is SideMenuItem; public static readonly DependencyProperty AutoSelectProperty = DependencyProperty.Register( nameof(AutoSelect), typeof(bool), typeof(SideMenu), new PropertyMetadata(ValueBoxes.TrueBox)); public bool AutoSelect { get => (bool) GetValue(AutoSelectProperty); set => SetValue(AutoSelectProperty, ValueBoxes.BooleanBox(value)); } public static readonly DependencyProperty ExpandModeProperty = DependencyProperty.Register( nameof(ExpandMode), typeof(ExpandMode), typeof(SideMenu), new PropertyMetadata(default(ExpandMode), OnExpandModeChanged)); private static void OnExpandModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctl = (SideMenu) d; var v = (ExpandMode) e.NewValue; if (ctl.ItemsHost == null) { return; } ctl.OnExpandModeChanged(v); } private void OnExpandModeChanged(ExpandMode mode) { if (mode == ExpandMode.ShowAll) { ShowAll(); } else if (mode == ExpandMode.ShowOne) { SideMenuItem sideMenuItemSelected = null; foreach (var sideMenuItem in ItemsHost.Children.OfType()) { if (sideMenuItemSelected != null) { sideMenuItem.IsSelected = false; if (sideMenuItem.ItemsHost != null) { foreach (var sideMenuSubItem in sideMenuItem.ItemsHost.Children.OfType()) { sideMenuSubItem.IsSelected = false; } } } else if (sideMenuItem.IsSelected) { switch (sideMenuItem.Role) { case SideMenuItemRole.Header: _selectedHeader = sideMenuItem; break; case SideMenuItemRole.Item: _selectedItem = sideMenuItem; break; } ShowSelectedOne(sideMenuItem); sideMenuItemSelected = sideMenuItem; if (sideMenuItem.ItemsHost != null) { foreach (var sideMenuSubItem in sideMenuItem.ItemsHost.Children.OfType()) { if (_selectedItem != null) { sideMenuSubItem.IsSelected = false; } else if (sideMenuSubItem.IsSelected) { _selectedItem = sideMenuSubItem; } } } } } } } public ExpandMode ExpandMode { get => (ExpandMode) GetValue(ExpandModeProperty); set => SetValue(ExpandModeProperty, value); } public static readonly DependencyProperty PanelAreaLengthProperty = DependencyProperty.Register( nameof(PanelAreaLength), typeof(double), typeof(SideMenu), new PropertyMetadata(double.NaN)); public double PanelAreaLength { get => (double) GetValue(PanelAreaLengthProperty); set => SetValue(PanelAreaLengthProperty, value); } private void ShowAll() { foreach (var sideMenuItem in ItemsHost.Children.OfType()) { sideMenuItem.SwitchPanelArea(true); } } private void ShowSelectedOne(SideMenuItem item) { foreach (var sideMenuItem in ItemsHost.Children.OfType()) { sideMenuItem.SwitchPanelArea(Equals(sideMenuItem, item)); } } public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent( "SelectionChanged", RoutingStrategy.Bubble, typeof(EventHandler>), typeof(SideMenu)); public event EventHandler> SelectionChanged { add => AddHandler(SelectionChangedEvent, value); remove => RemoveHandler(SelectionChangedEvent, value); } }