Skip to content

Commit 721a25c

Browse files
Ensure padding on tab headers is only applied when they overflow
There is no need for the padding if all tabs can fit inside the visible region.
1 parent 0511117 commit 721a25c

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

src/MaterialDesignThemes.Wpf/Behaviors/Internal/TabControlHeaderScrollBehavior.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,42 @@ public TabControl TabControl
3333
DependencyProperty.Register(nameof(TabControl), typeof(TabControl),
3434
typeof(TabControlHeaderScrollBehavior), new PropertyMetadata(null, OnTabControlChanged));
3535

36+
3637
private static void OnTabControlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
3738
{
3839
var behavior = (TabControlHeaderScrollBehavior)d;
3940
if (e.OldValue is TabControl oldTabControl)
4041
{
4142
oldTabControl.SelectionChanged -= behavior.OnTabChanged;
43+
oldTabControl.SizeChanged -= behavior.OnTabControlSizeChanged;
4244
}
4345
if (e.NewValue is TabControl newTabControl)
4446
{
4547
newTabControl.SelectionChanged += behavior.OnTabChanged;
48+
newTabControl.SizeChanged += behavior.OnTabControlSizeChanged;
4649
}
4750
}
4851

52+
public FrameworkElement ScrollableContent
53+
{
54+
get => (FrameworkElement)GetValue(ScrollableContentProperty);
55+
set => SetValue(ScrollableContentProperty, value);
56+
}
57+
58+
public static readonly DependencyProperty ScrollableContentProperty =
59+
DependencyProperty.Register(nameof(ScrollableContent), typeof(FrameworkElement),
60+
typeof(TabControlHeaderScrollBehavior), new PropertyMetadata(null, OnScrollableContentChanged));
61+
62+
private static void OnScrollableContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
63+
{
64+
var behavior = (TabControlHeaderScrollBehavior)d;
65+
behavior.AddPaddingToScrollableContentIfWiderThanViewPort();
66+
}
67+
68+
internal const double ScrollOffset = 40; // MD spec says 52 DP, but that seems a little excessive in practice
69+
internal static readonly Thickness ScrollableContentPadding = new(ScrollOffset, 0, ScrollOffset, 0);
70+
internal static readonly Thickness NoScrollableContentPadding = new(0);
71+
4972
private double? _desiredScrollStart;
5073
private bool _isAnimatingScroll;
5174

@@ -70,10 +93,30 @@ bool IsMovingForward()
7093
int GetItemIndex(object? item) => tabControl.Items.IndexOf(item);
7194
}
7295

96+
private void OnTabControlSizeChanged(object sender, SizeChangedEventArgs _) => AddPaddingToScrollableContentIfWiderThanViewPort();
97+
private void AssociatedObject_SizeChanged(object sender, SizeChangedEventArgs _) => AddPaddingToScrollableContentIfWiderThanViewPort();
98+
99+
private void AddPaddingToScrollableContentIfWiderThanViewPort()
100+
{
101+
if (ScrollableContent is null)
102+
return;
103+
104+
if (ScrollableContent.ActualWidth > TabControl.ActualWidth)
105+
{
106+
ScrollableContent.Margin = ScrollableContentPadding;
107+
}
108+
else
109+
{
110+
ScrollableContent.Margin = NoScrollableContentPadding;
111+
}
112+
}
113+
73114
protected override void OnAttached()
74115
{
75116
base.OnAttached();
76117
AssociatedObject.ScrollChanged += AssociatedObject_ScrollChanged;
118+
AssociatedObject.SizeChanged += AssociatedObject_SizeChanged;
119+
Dispatcher.BeginInvoke(() => AddPaddingToScrollableContentIfWiderThanViewPort());
77120
}
78121

79122
protected override void OnDetaching()
@@ -82,6 +125,7 @@ protected override void OnDetaching()
82125
if (AssociatedObject is { } ao)
83126
{
84127
ao.ScrollChanged -= AssociatedObject_ScrollChanged;
128+
ao.SizeChanged -= AssociatedObject_SizeChanged;
85129
}
86130
}
87131

src/MaterialDesignThemes.Wpf/Internal/BringIntoViewHijackingStackPanel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ private void OnRequestBringIntoView(object sender, RoutedEventArgs e)
2424
{
2525
e.Handled = true;
2626
double offset = TabScrollDirection switch {
27-
TabScrollDirection.Backward => -52,
28-
TabScrollDirection.Forward => 52,
27+
TabScrollDirection.Backward => -TabControlHeaderScrollBehavior.ScrollOffset,
28+
TabScrollDirection.Forward => TabControlHeaderScrollBehavior.ScrollOffset,
2929
_ => 0
3030
};
3131
var point = child.TranslatePoint(new Point(), this);

src/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TabControl.xaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@
4040
HorizontalScrollBarVisibility="Hidden"
4141
VerticalScrollBarVisibility="Hidden">
4242
<b:Interaction.Behaviors>
43-
<behaviorsInternal:TabControlHeaderScrollBehavior TabControl="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
43+
<behaviorsInternal:TabControlHeaderScrollBehavior TabControl="{Binding RelativeSource={RelativeSource TemplatedParent}}" ScrollableContent="{Binding ElementName=ScrollableContent}" />
4444
</b:Interaction.Behaviors>
45-
<internal:BringIntoViewHijackingStackPanel TabScrollDirection="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(behaviorsInternal:TabControlHeaderScrollBehavior.TabScrollDirection)}">
45+
<internal:BringIntoViewHijackingStackPanel x:Name="ScrollableContent" TabScrollDirection="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(behaviorsInternal:TabControlHeaderScrollBehavior.TabScrollDirection)}">
4646
<UniformGrid x:Name="CenteredHeaderPanel"
4747
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
4848
Margin="{Binding Path=(wpf:TabAssist.HeaderPanelMargin), RelativeSource={RelativeSource TemplatedParent}}"

0 commit comments

Comments
 (0)