support for tab switching
This commit is contained in:
1 parent
eb2779fa2a
commit
41c661da1a
5 files changed
+186
-136
No files matched your search
@@ -10867,7 +10867,7 @@
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
|
||||
<Setter Property="Background" Value="{DynamicResource RegionBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource TitleBrush}" />
|
||||
<Setter Property="Margin" Value="0" />
|
||||
<Setter Property="Padding" Value="{StaticResource DefaultControlPadding}" />
|
||||
<Setter Property="MinHeight" Value="{StaticResource DefaultControlHeight}" />
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
using HandyControl.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
@@ -19,25 +16,48 @@ namespace HandyControl.Controls
|
||||
|
||||
private readonly ObservableCollection<object> _tabHeaderItemsSource = new();
|
||||
|
||||
internal ItemsControl RibbonTabHeaderItemsControl => _tabHeaderItemsControl;
|
||||
|
||||
public Ribbon()
|
||||
{
|
||||
SetRibbon(this, this);
|
||||
ItemContainerGenerator.StatusChanged += OnItemContainerGeneratorStatusChanged;
|
||||
|
||||
AddHandler(SelectableItem.SelectedEvent, new RoutedEventHandler(OnTabHeaderSelected));
|
||||
}
|
||||
|
||||
private void OnTabHeaderSelected(object sender, RoutedEventArgs e)
|
||||
internal static readonly DependencyProperty RibbonProperty = DependencyProperty.RegisterAttached(
|
||||
"Ribbon", typeof(Ribbon), typeof(Ribbon),
|
||||
new FrameworkPropertyMetadata(default(Ribbon), FrameworkPropertyMetadataOptions.Inherits));
|
||||
|
||||
internal static void SetRibbon(DependencyObject element, Ribbon value)
|
||||
=> element.SetValue(RibbonProperty, value);
|
||||
|
||||
internal static Ribbon GetRibbon(DependencyObject element)
|
||||
=> (Ribbon) element.GetValue(RibbonProperty);
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_tabHeaderItemsControl = GetTemplateChild(TabHeaderItemsControl) as ItemsControl;
|
||||
if (_tabHeaderItemsControl is {ItemsSource: null})
|
||||
{
|
||||
_tabHeaderItemsControl.ItemsSource = _tabHeaderItemsSource;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ResetSelection()
|
||||
{
|
||||
SelectedIndex = -1;
|
||||
InitializeSelection();
|
||||
}
|
||||
|
||||
internal void NotifyMouseClickedOnTabHeader(RibbonTabHeader tabHeader)
|
||||
{
|
||||
if (_tabHeaderItemsControl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.OriginalSource is not RibbonTabHeader tabHeader)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedIndex = _tabHeaderItemsControl.ItemContainerGenerator.IndexFromContainer(tabHeader);
|
||||
var currentSelectedIndex = SelectedIndex;
|
||||
|
||||
@@ -47,73 +67,14 @@ namespace HandyControl.Controls
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly DependencyPropertyKey SelectedContentPropertyKey =
|
||||
DependencyProperty.RegisterReadOnly("SelectedContent", typeof(object), typeof(Ribbon),
|
||||
new FrameworkPropertyMetadata((object) null));
|
||||
|
||||
public static readonly DependencyProperty SelectedContentProperty =
|
||||
SelectedContentPropertyKey.DependencyProperty;
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public object SelectedContent
|
||||
internal void NotifyTabHeaderChanged()
|
||||
{
|
||||
get => GetValue(SelectedContentProperty);
|
||||
internal set => SetValue(SelectedContentPropertyKey, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsMinimizedProperty = DependencyProperty.Register(nameof(IsMinimized),
|
||||
typeof(bool), typeof(Ribbon),
|
||||
new PropertyMetadata(ValueBoxes.FalseBox, OnIsMinimizedChanged, CoerceIsMinimized));
|
||||
|
||||
private static object CoerceIsMinimized(DependencyObject d, object basevalue)
|
||||
{
|
||||
var num = (bool) basevalue ? 1 : 0;
|
||||
var ribbon = (Ribbon) d;
|
||||
return num != 0 && ribbon.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated ? ValueBoxes.FalseBox : basevalue;
|
||||
}
|
||||
|
||||
private static void OnIsMinimizedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool IsMinimized
|
||||
{
|
||||
get => (bool) GetValue(IsMinimizedProperty);
|
||||
set => SetValue(IsMinimizedProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsDropDownOpenProperty =
|
||||
DependencyProperty.Register(nameof(IsDropDownOpen), typeof(bool), typeof(Ribbon),
|
||||
new PropertyMetadata(ValueBoxes.FalseBox, OnIsDropDownOpenChanged, CoerceIsDropDownOpen));
|
||||
|
||||
private static object CoerceIsDropDownOpen(DependencyObject d, object basevalue)
|
||||
{
|
||||
return ValueBoxes.FalseBox;
|
||||
}
|
||||
|
||||
private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public bool IsDropDownOpen
|
||||
{
|
||||
get => (bool) GetValue(IsDropDownOpenProperty);
|
||||
set => SetValue(IsDropDownOpenProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_tabHeaderItemsControl = GetTemplateChild(TabHeaderItemsControl) as ItemsControl;
|
||||
if (_tabHeaderItemsControl is {ItemsSource: null})
|
||||
if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
|
||||
{
|
||||
_tabHeaderItemsControl.ItemsSource = _tabHeaderItemsSource;
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateSelectedContent();
|
||||
RefreshHeaderCollection();
|
||||
}
|
||||
|
||||
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
|
||||
@@ -140,6 +101,23 @@ namespace HandyControl.Controls
|
||||
|
||||
protected override bool IsItemItsOwnContainerOverride(object item) => item is RibbonTab;
|
||||
|
||||
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
|
||||
{
|
||||
base.OnSelectionChanged(e);
|
||||
|
||||
if (e.AddedItems is not {Count: > 0})
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.RemovedItems.Count > 0 && ItemContainerGenerator.ContainerFromItem(e.RemovedItems[0]) is RibbonTab oldRibbonTab)
|
||||
{
|
||||
oldRibbonTab.IsSelected = false;
|
||||
}
|
||||
|
||||
SelectedItem = e.AddedItems[0];
|
||||
}
|
||||
|
||||
private void OnItemContainerGeneratorStatusChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
|
||||
@@ -147,7 +125,6 @@ namespace HandyControl.Controls
|
||||
return;
|
||||
}
|
||||
|
||||
CoerceValue(Ribbon.IsMinimizedProperty);
|
||||
InitializeSelection();
|
||||
RefreshHeaderCollection();
|
||||
}
|
||||
@@ -182,58 +159,6 @@ namespace HandyControl.Controls
|
||||
SelectedIndex = firstVisibleTabIndex;
|
||||
}
|
||||
|
||||
private static bool EqualsEx(object o1, object o2)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Equals(o1, o2);
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private RibbonTab GetSelectedRibbonTab()
|
||||
{
|
||||
var selectedItem = SelectedItem;
|
||||
if (selectedItem != null)
|
||||
{
|
||||
if (selectedItem is not RibbonTab ribbonTab)
|
||||
{
|
||||
ribbonTab = ItemContainerGenerator.ContainerFromIndex(SelectedIndex) as RibbonTab;
|
||||
|
||||
if (ribbonTab == null || !EqualsEx(selectedItem, ItemContainerGenerator.ItemFromContainer(ribbonTab)))
|
||||
{
|
||||
ribbonTab = ItemContainerGenerator.ContainerFromItem(selectedItem) as RibbonTab;
|
||||
}
|
||||
}
|
||||
|
||||
return ribbonTab;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void UpdateSelectedContent()
|
||||
{
|
||||
if (SelectedIndex < 0)
|
||||
{
|
||||
SelectedContent = null;
|
||||
return;
|
||||
}
|
||||
|
||||
var ribbonTab = GetSelectedRibbonTab();
|
||||
if (ribbonTab == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var visualParent = VisualTreeHelper.GetParent(ribbonTab) as FrameworkElement;
|
||||
|
||||
//seitem
|
||||
}
|
||||
|
||||
private static object CreateDefaultHeaderObject() => new SingleSpaceObject();
|
||||
|
||||
private void RefreshHeaderCollection()
|
||||
|
||||
@@ -1,13 +1,58 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class RibbonTab : HeaderedItemsControl
|
||||
{
|
||||
public Ribbon Ribbon => Ribbon.GetRibbon(this);
|
||||
|
||||
internal RibbonTabHeader RibbonTabHeader
|
||||
{
|
||||
get
|
||||
{
|
||||
var ribbon = Ribbon;
|
||||
if (ribbon == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var index = ribbon.ItemContainerGenerator.IndexFromContainer(this);
|
||||
if (index < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var headerItemsControl = ribbon.RibbonTabHeaderItemsControl;
|
||||
return headerItemsControl?.ItemContainerGenerator.ContainerFromIndex(index) as RibbonTabHeader;
|
||||
}
|
||||
}
|
||||
|
||||
static RibbonTab()
|
||||
{
|
||||
VisibilityProperty.OverrideMetadata(typeof(RibbonTab), new PropertyMetadata(Visibility.Visible, OnVisibilityChanged));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
|
||||
"IsSelected", typeof(bool), typeof(RibbonTab), new PropertyMetadata(ValueBoxes.FalseBox));
|
||||
"IsSelected", typeof(bool), typeof(RibbonTab), new PropertyMetadata(ValueBoxes.FalseBox, OnIsSelectedChanged));
|
||||
|
||||
private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ribbonTab = (RibbonTab) d;
|
||||
if (ribbonTab.IsSelected)
|
||||
{
|
||||
ribbonTab.OnSelected(new RoutedEventArgs(Selector.SelectedEvent, ribbonTab));
|
||||
}
|
||||
else
|
||||
{
|
||||
ribbonTab.OnUnselected(new RoutedEventArgs(Selector.UnselectedEvent, ribbonTab));
|
||||
}
|
||||
|
||||
ribbonTab.RibbonTabHeader?.CoerceValue(RibbonTabHeader.IsSelectedProperty);
|
||||
}
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
@@ -15,6 +60,32 @@ namespace HandyControl.Controls
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
|
||||
protected virtual void OnSelected(RoutedEventArgs e) => RaiseEvent(e);
|
||||
|
||||
protected virtual void OnUnselected(RoutedEventArgs e) => RaiseEvent(e);
|
||||
|
||||
protected override void OnHeaderChanged(object oldHeader, object newHeader)
|
||||
{
|
||||
base.OnHeaderChanged(oldHeader, newHeader);
|
||||
Ribbon?.NotifyTabHeaderChanged();
|
||||
}
|
||||
|
||||
private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ribbonTab = (RibbonTab) d;
|
||||
var ribbon = ribbonTab.Ribbon;
|
||||
|
||||
if (ribbon == null ||
|
||||
!ribbonTab.IsSelected ||
|
||||
(Visibility) e.OldValue != Visibility.Visible ||
|
||||
(Visibility) e.NewValue == Visibility.Visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ribbon.ResetSelection();
|
||||
}
|
||||
|
||||
protected override DependencyObject GetContainerForItemOverride() => new RibbonGroup();
|
||||
|
||||
protected override bool IsItemItsOwnContainerOverride(object item) => item is RibbonGroup;
|
||||
|
||||
@@ -1,7 +1,62 @@
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class RibbonTabHeader : SelectableItem
|
||||
{
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using HandyControl.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
{
|
||||
public class RibbonTabHeader : ContentControl
|
||||
{
|
||||
public Ribbon Ribbon => Ribbon.GetRibbon(this);
|
||||
|
||||
internal RibbonTab RibbonTab
|
||||
{
|
||||
get
|
||||
{
|
||||
var itemsControl = ItemsControl.ItemsControlFromItemContainer(this);
|
||||
var ribbon = Ribbon;
|
||||
if (itemsControl == null || ribbon == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var index = itemsControl.ItemContainerGenerator.IndexFromContainer(this);
|
||||
return ribbon.ItemContainerGenerator.ContainerFromIndex(index) as RibbonTab;
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
|
||||
"IsSelected", typeof(bool), typeof(RibbonTabHeader),
|
||||
new PropertyMetadata(ValueBoxes.FalseBox, OnIsSelectedChanged, CoerceIsSelected));
|
||||
|
||||
private static object CoerceIsSelected(DependencyObject d, object basevalue)
|
||||
{
|
||||
var ribbonTab = ((RibbonTabHeader) d).RibbonTab;
|
||||
return ribbonTab != null ? ValueBoxes.BooleanBox(ribbonTab.IsSelected) : basevalue;
|
||||
}
|
||||
|
||||
private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((RibbonTabHeader) d).OnIsSelectedChanged((bool) e.OldValue, (bool) e.NewValue);
|
||||
}
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => (bool) GetValue(IsSelectedProperty);
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
|
||||
protected virtual void OnIsSelectedChanged(bool oldIsSelected, bool newIsSelected)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
|
||||
{
|
||||
base.OnMouseLeftButtonDown(e);
|
||||
|
||||
Ribbon.NotifyMouseClickedOnTabHeader(this);
|
||||
RibbonTab.IsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,6 @@
|
||||
<Setter Property="Foreground" Value="{DynamicResource SecondaryTextBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource TitleBrush}"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="SelfManage" Value="True"/>
|
||||
<Setter Property="Padding" Value="{StaticResource DefaultControlPadding}"/>
|
||||
<Setter Property="MinHeight" Value="{StaticResource DefaultControlHeight}"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
@@ -85,7 +84,7 @@
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="hc:RibbonTab">
|
||||
<hc:SimplePanel>
|
||||
<hc:SimplePanel Visibility="{Binding IsSelected,RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}">
|
||||
<Border x:Name="mainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0,0,0,3" Background="{TemplateBinding Background}" Margin="0"/>
|
||||
<ItemsPresenter/>
|
||||
</hc:SimplePanel>
|
||||
@@ -112,7 +111,7 @@
|
||||
<ControlTemplate TargetType="hc:Ribbon">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
Reference in new issue
Block a user