From 2cd530c4678d6e3aaf3de0b81ed456f7e7ea834b Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Sat, 7 Aug 2021 18:38:45 +0800 Subject: [PATCH] Ribbon support for IsDropDownOpen --- .../Controls/Ribbon/Ribbon.cs | 151 ++++++++++++++++-- .../Ribbon/RibbonTabHeaderItemsControl.cs | 9 +- .../Controls/Ribbon/RibbonTabsPanel.cs | 11 ++ .../HandyControl_Shared.projitems | 1 + .../Themes/Styles/Ribbon.xaml | 55 ++++--- 5 files changed, 195 insertions(+), 32 deletions(-) create mode 100644 src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabsPanel.cs diff --git a/src/Shared/HandyControl_Shared/Controls/Ribbon/Ribbon.cs b/src/Shared/HandyControl_Shared/Controls/Ribbon/Ribbon.cs index 2ae4e8ac..9f11bf14 100644 --- a/src/Shared/HandyControl_Shared/Controls/Ribbon/Ribbon.cs +++ b/src/Shared/HandyControl_Shared/Controls/Ribbon/Ribbon.cs @@ -5,6 +5,8 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; +using HandyControl.Data; +using HandyControl.Interactivity; namespace HandyControl.Controls { @@ -15,6 +17,8 @@ namespace HandyControl.Controls private ItemsControl _tabHeaderItemsControl; + private System.Windows.Window _window; + private readonly ObservableCollection _tabHeaderItemsSource = new(); internal ItemsControl RibbonTabHeaderItemsControl => _tabHeaderItemsControl; @@ -22,7 +26,12 @@ namespace HandyControl.Controls public Ribbon() { SetRibbon(this, this); + + Loaded += Ribbon_Loaded; + Unloaded += Ribbon_Unloaded; + ItemContainerGenerator.StatusChanged += OnItemContainerGeneratorStatusChanged; + CommandBindings.Add(new CommandBinding(ControlCommands.Switch, IsMinimizedSwitchButton_OnClick)); } internal static readonly DependencyProperty RibbonProperty = DependencyProperty.RegisterAttached( @@ -35,6 +44,33 @@ namespace HandyControl.Controls internal static Ribbon GetRibbon(DependencyObject element) => (Ribbon) element.GetValue(RibbonProperty); + public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register( + "IsDropDownOpen", typeof(bool), typeof(Ribbon), new PropertyMetadata(ValueBoxes.TrueBox)); + + public bool IsDropDownOpen + { + get => (bool) GetValue(IsDropDownOpenProperty); + set => SetValue(IsDropDownOpenProperty, value); + } + + public static readonly DependencyProperty IsMinimizedProperty = DependencyProperty.Register( + "IsMinimized", typeof(bool), typeof(Ribbon), new PropertyMetadata(ValueBoxes.FalseBox)); + + public bool IsMinimized + { + get => (bool) GetValue(IsMinimizedProperty); + set => SetValue(IsMinimizedProperty, value); + } + + public static readonly DependencyProperty ContentHeightProperty = DependencyProperty.Register( + "ContentHeight", typeof(double), typeof(Ribbon), new PropertyMetadata(default(double))); + + public double ContentHeight + { + get => (double) GetValue(ContentHeightProperty); + set => SetValue(ContentHeightProperty, value); + } + public override void OnApplyTemplate() { base.OnApplyTemplate(); @@ -60,11 +96,45 @@ namespace HandyControl.Controls } var selectedIndex = _tabHeaderItemsControl.ItemContainerGenerator.IndexFromContainer(tabHeader); - var currentSelectedIndex = SelectedIndex; - if (currentSelectedIndex < 0 || SelectedIndex != selectedIndex) + if (e.ClickCount == 1) { - SelectedIndex = selectedIndex; + var currentSelectedIndex = SelectedIndex; + + if (currentSelectedIndex < 0 || currentSelectedIndex != selectedIndex) + { + SelectedIndex = selectedIndex; + + if (IsMinimized) + { + IsDropDownOpen = true; + } + } + else + { + if (IsMinimized) + { + IsDropDownOpen = !IsDropDownOpen; + if (!IsDropDownOpen) + { + SelectedIndex = -1; + } + } + } + } + else if (e.ClickCount == 2) + { + IsMinimized = !IsMinimized; + IsDropDownOpen = !IsMinimized; + + if (IsMinimized && !IsDropDownOpen) + { + SelectedIndex = -1; + } + else + { + SelectedIndex = selectedIndex; + } } } @@ -89,8 +159,8 @@ namespace HandyControl.Controls InitializeSelection(); } - if ((ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated || e.Action != NotifyCollectionChangedAction.Move) && - e.Action != NotifyCollectionChangedAction.Remove) + if ((ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated || + e.Action != NotifyCollectionChangedAction.Move) && e.Action != NotifyCollectionChangedAction.Remove) { return; } @@ -114,6 +184,68 @@ namespace HandyControl.Controls SelectedItem = e.AddedItems[0]; } + private void OnPreviewMouseButton(MouseButtonEventArgs e) + { + var postion = e.GetPosition(this); + if (InputHitTest(postion) == null) + { + if (IsMinimized && IsDropDownOpen) + { + IsDropDownOpen = false; + SelectedIndex = -1; + } + } + } + + private void Ribbon_Loaded(object sender, RoutedEventArgs e) + { + _window = System.Windows.Window.GetWindow(this); + if (_window != null) + { + _window.Deactivated += Window_Deactivated; + _window.PreviewMouseLeftButtonDown += Window_PreviewMouseLeftButtonDown; + _window.PreviewMouseLeftButtonUp += Window_PreviewMouseLeftButtonUp; + _window.PreviewMouseRightButtonDown += Window_PreviewMouseRightButtonDown; + _window.PreviewMouseRightButtonUp += Window_PreviewMouseRightButtonUp; + } + + UpdateLayout(); + } + + private void Ribbon_Unloaded(object sender, RoutedEventArgs e) + { + if (_window != null) + { + _window.Deactivated -= Window_Deactivated; + } + } + + private void Window_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e); + + private void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e); + + private void Window_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e); + + private void Window_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e) => OnPreviewMouseButton(e); + + private void Window_Deactivated(object sender, EventArgs e) + { + if (IsMinimized && IsDropDownOpen) + { + IsDropDownOpen = false; + SelectedIndex = -1; + } + } + + private void IsMinimizedSwitchButton_OnClick(object sender, ExecutedRoutedEventArgs e) + { + IsDropDownOpen = !IsMinimized; + if (!IsDropDownOpen) + { + SelectedIndex = -1; + } + } + private void OnItemContainerGeneratorStatusChanged(object sender, EventArgs e) { if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) @@ -155,8 +287,6 @@ namespace HandyControl.Controls SelectedIndex = firstVisibleTabIndex; } - private static object CreateDefaultHeaderObject() => new SingleSpaceObject(); - private void RefreshHeaderCollection() { var itemsCount = Items.Count; @@ -168,7 +298,7 @@ namespace HandyControl.Controls header = ribbonTab.Header; } - header ??= CreateDefaultHeaderObject(); + header ??= string.Empty; if (index >= _tabHeaderItemsSource.Count) { @@ -186,10 +316,5 @@ namespace HandyControl.Controls _tabHeaderItemsSource.RemoveAt(itemsCount); } } - - private class SingleSpaceObject - { - public override string ToString() => " "; - } } } diff --git a/src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabHeaderItemsControl.cs b/src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabHeaderItemsControl.cs index 5e0720fe..cb23e211 100644 --- a/src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabHeaderItemsControl.cs +++ b/src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabHeaderItemsControl.cs @@ -1,4 +1,5 @@ -using System.Windows; +using System.Collections.Specialized; +using System.Windows; using System.Windows.Controls; namespace HandyControl.Controls @@ -18,5 +19,11 @@ namespace HandyControl.Controls ribbonTabHeader.PrepareRibbonTabHeader(); } } + + protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) + { + base.OnItemsChanged(e); + var r = this.RenderSize; + } } } diff --git a/src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabsPanel.cs b/src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabsPanel.cs new file mode 100644 index 00000000..17d2986b --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Ribbon/RibbonTabsPanel.cs @@ -0,0 +1,11 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace HandyControl.Controls +{ + public class RibbonTabsPanel : Grid + { + protected override Geometry GetLayoutClip(Size layoutSlotSize) => null; + } +} diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index 02e54593..ce129c44 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -78,6 +78,7 @@ + diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Ribbon.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Ribbon.xaml index 48c6d4db..6e75125f 100644 --- a/src/Shared/HandyControl_Shared/Themes/Styles/Ribbon.xaml +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Ribbon.xaml @@ -1,6 +1,8 @@  + xmlns:hc="clr-namespace:HandyControl.Controls" + xmlns:interactivity="clr-namespace:HandyControl.Interactivity" + xmlns:system="clr-namespace:System;assembly=mscorlib"> M878.3 392.1L631.9 145.7c-6.5-6.5-15-9.7-23.5-9.7s-17 3.2-23.5 9.7L423.8 306.9c-12.2-1.4-24.5-2-36.8-2-73.2 0-146.4 24.1-206.5 72.3-15.4 12.3-16.6 35.4-2.7 49.4l181.7 181.7-215.4 215.2c-2.6 2.6-4.3 6.1-4.6 9.8l-3.4 37.2c-0.9 9.4 6.6 17.4 15.9 17.4 0.5 0 1 0 1.5-0.1l37.2-3.4c3.7-0.3 7.2-2 9.8-4.6l215.4-215.4 181.7 181.7c6.5 6.5 15 9.7 23.5 9.7 9.7 0 19.3-4.2 25.9-12.4 56.3-70.3 79.7-158.3 70.2-243.4l161.1-161.1c12.9-12.8 12.9-33.8 0-46.8z M0,0 8,0 8,1 1,1 1,8 0,8 M 3.7,3 8,7.3 8,4 9,4 9,9 4,9 4,8 7.3,8 3,3.7 @@ -100,7 +102,9 @@