Skip to content

Commit 55579e1

Browse files
committed
added AP to be able to swap between a scrollable and a wrapping header panel in a TabControl
1 parent cf1afbc commit 55579e1

File tree

4 files changed

+157
-31
lines changed

4 files changed

+157
-31
lines changed

src/MainDemo.Wpf/Domain/TabsViewModel.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
namespace MaterialDesignDemo.Domain;
66

7-
internal class TabsViewModel : ViewModelBase
7+
internal partial class TabsViewModel : ObservableObject
88
{
99
public ObservableCollection<CustomTab> CustomTabs { get; }
10-
10+
public List<int> LongList { get; }
1111
public CustomTab? SelectedTab { get; set; }
1212

1313
public string? VeryLongText { get; set; } = @"
@@ -47,6 +47,8 @@ public TabsViewModel()
4747
CustomContent = "Custom content 3",
4848
},
4949
};
50+
51+
LongList = Enumerable.Range(1, 20).ToList();
5052
}
5153

5254
}

src/MainDemo.Wpf/Tabs.xaml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,5 +755,87 @@
755755
</materialDesign:Card>
756756
</smtx:XamlDisplay>
757757

758+
<Border Width="720"
759+
BorderBrush="{DynamicResource MaterialDesign.Brush.Primary}"
760+
BorderThickness="1">
761+
<Grid>
762+
<Grid.RowDefinitions>
763+
<RowDefinition Height="auto" />
764+
<RowDefinition Height="*" />
765+
</Grid.RowDefinitions>
766+
<Grid.ColumnDefinitions>
767+
<ColumnDefinition Width="*" MinWidth="50" />
768+
<ColumnDefinition Width="2" />
769+
<ColumnDefinition Width="*" MinWidth="50" />
770+
</Grid.ColumnDefinitions>
771+
772+
<materialDesign:ColorZone Grid.ColumnSpan="2"
773+
Padding="8"
774+
Mode="PrimaryMid">
775+
<TextBlock Text="materialDesign:TabAssist.HeaderBehavior=&quot;Scrolling&quot;" />
776+
</materialDesign:ColorZone>
777+
778+
<materialDesign:ColorZone Grid.Column="2"
779+
Padding="8"
780+
Mode="PrimaryMid">
781+
<TextBlock Text="materialDesign:TabAssist.HeaderBehavior=&quot;Wrapping&quot;" />
782+
</materialDesign:ColorZone>
783+
784+
<smtx:XamlDisplay Grid.Row="1"
785+
Grid.Column="0"
786+
Margin="16"
787+
UniqueKey="tabs_tabAssist_1">
788+
<TabControl materialDesign:TabAssist.HeaderBehavior="Scrolling"
789+
ItemsSource="{Binding LongList}"
790+
Style="{StaticResource MaterialDesignTabControl}">
791+
<TabControl.ItemTemplate>
792+
<DataTemplate>
793+
<StackPanel Orientation="Horizontal">
794+
<TextBlock Text="{Binding ., StringFormat=Header {0}}" />
795+
</StackPanel>
796+
</DataTemplate>
797+
</TabControl.ItemTemplate>
798+
<TabControl.ContentTemplate>
799+
<DataTemplate>
800+
<TextBlock Margin="10"
801+
FontSize="18"
802+
Text="{Binding ., StringFormat=Content {0}}" />
803+
</DataTemplate>
804+
</TabControl.ContentTemplate>
805+
</TabControl>
806+
</smtx:XamlDisplay>
807+
808+
<GridSplitter Grid.RowSpan="2"
809+
Grid.Column="1"
810+
HorizontalAlignment="Stretch"
811+
VerticalAlignment="Stretch" />
812+
813+
<smtx:XamlDisplay Grid.Row="1"
814+
Grid.Column="2"
815+
Margin="16"
816+
UniqueKey="tabs_tabAssist_2">
817+
<TabControl materialDesign:TabAssist.HeaderBehavior="Wrapping"
818+
ItemsSource="{Binding LongList}"
819+
Style="{StaticResource MaterialDesignTabControl}">
820+
<TabControl.ItemTemplate>
821+
<DataTemplate>
822+
<StackPanel Orientation="Horizontal">
823+
<TextBlock Text="{Binding ., StringFormat=Header {0}}" />
824+
</StackPanel>
825+
</DataTemplate>
826+
</TabControl.ItemTemplate>
827+
<TabControl.ContentTemplate>
828+
<DataTemplate>
829+
<TextBlock Margin="10"
830+
FontSize="18"
831+
Text="{Binding ., StringFormat=Content {0}}" />
832+
</DataTemplate>
833+
</TabControl.ContentTemplate>
834+
</TabControl>
835+
</smtx:XamlDisplay>
836+
837+
</Grid>
838+
</Border>
839+
758840
</StackPanel>
759841
</UserControl>

src/MaterialDesignThemes.Wpf/TabAssist.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
namespace MaterialDesignThemes.Wpf;
22

3+
public enum TabControlHeaderBehavior
4+
{
5+
Scrolling,
6+
Wrapping
7+
}
8+
39
public static class TabAssist
410
{
511
public static readonly DependencyProperty HasFilledTabProperty = DependencyProperty.RegisterAttached(
@@ -27,7 +33,7 @@ public static void SetHeaderPanelMargin(DependencyObject element, Thickness valu
2733
=> element.SetValue(HeaderPanelMarginProperty, value);
2834

2935
public static Thickness GetHeaderPanelMargin(DependencyObject element)
30-
=> (Thickness) element.GetValue(HeaderPanelMarginProperty);
36+
=> (Thickness)element.GetValue(HeaderPanelMarginProperty);
3137

3238
internal static Visibility GetBindableIsItemsHost(DependencyObject obj)
3339
=> (Visibility)obj.GetValue(BindableIsItemsHostProperty);
@@ -45,4 +51,14 @@ private static void OnBindableIsItemsHostChanged(DependencyObject d, DependencyP
4551
panel.IsItemsHost = (Visibility)e.NewValue == Visibility.Visible;
4652
}
4753
}
54+
55+
public static TabControlHeaderBehavior GetHeaderBehavior(DependencyObject obj)
56+
=> (TabControlHeaderBehavior)obj.GetValue(HeaderBehaviorProperty);
57+
58+
public static void SetHeaderBehavior(DependencyObject obj, TabControlHeaderBehavior value)
59+
=> obj.SetValue(HeaderBehaviorProperty, value);
60+
61+
public static readonly DependencyProperty HeaderBehaviorProperty =
62+
DependencyProperty.RegisterAttached("HeaderBehavior", typeof(TabControlHeaderBehavior), typeof(TabAssist),
63+
new PropertyMetadata(TabControlHeaderBehavior.Scrolling));
4864
}

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

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,57 +31,83 @@
3131
<ControlTemplate TargetType="{x:Type TabControl}">
3232
<DockPanel KeyboardNavigation.TabNavigation="Local">
3333
<wpf:ColorZone x:Name="PART_HeaderZone"
34-
VerticalAlignment="Stretch"
35-
Panel.ZIndex="1"
36-
wpf:ElevationAssist.Elevation="{TemplateBinding wpf:ElevationAssist.Elevation}"
37-
Background="{TemplateBinding wpf:ColorZoneAssist.Background}"
38-
DockPanel.Dock="Top"
39-
Focusable="False">
40-
<ScrollViewer wpf:ScrollViewerAssist.BubbleVerticalScroll="True"
41-
wpf:ScrollViewerAssist.SupportHorizontalScroll="True"
34+
VerticalAlignment="Stretch"
35+
Panel.ZIndex="1"
36+
wpf:ElevationAssist.Elevation="{TemplateBinding wpf:ElevationAssist.Elevation}"
37+
Background="{TemplateBinding wpf:ColorZoneAssist.Background}"
38+
DockPanel.Dock="Top"
39+
Focusable="False">
40+
<Grid>
41+
<!-- Scrollable headers -->
42+
<ScrollViewer x:Name="PART_HeaderScrollViewer"
43+
wpf:ScrollViewerAssist.BubbleVerticalScroll="True"
4244
wpf:ScrollViewerAssist.IgnorePadding="{Binding Path=(wpf:ScrollViewerAssist.IgnorePadding), RelativeSource={RelativeSource TemplatedParent}}"
4345
wpf:ScrollViewerAssist.PaddingMode="{Binding Path=(wpf:ScrollViewerAssist.PaddingMode), RelativeSource={RelativeSource TemplatedParent}}"
46+
wpf:ScrollViewerAssist.SupportHorizontalScroll="True"
4447
HorizontalScrollBarVisibility="Hidden"
4548
VerticalScrollBarVisibility="Hidden">
46-
<StackPanel>
47-
<UniformGrid x:Name="CenteredHeaderPanel"
48-
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
49+
<StackPanel>
50+
<UniformGrid x:Name="CenteredHeaderPanel"
4951
Margin="{Binding Path=(wpf:TabAssist.HeaderPanelMargin), RelativeSource={RelativeSource TemplatedParent}}"
52+
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
5053
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
5154
wpf:TabAssist.BindableIsItemsHost="{Binding Visibility, RelativeSource={RelativeSource Self}}"
5255
Focusable="False"
5356
KeyboardNavigation.TabIndex="1"
5457
Rows="1" />
55-
<VirtualizingStackPanel x:Name="HeaderPanel"
56-
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
58+
<VirtualizingStackPanel x:Name="HeaderPanel"
5759
Margin="{Binding Path=(wpf:TabAssist.HeaderPanelMargin), RelativeSource={RelativeSource TemplatedParent}}"
60+
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
5861
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
5962
wpf:TabAssist.BindableIsItemsHost="{Binding Visibility, RelativeSource={RelativeSource Self}}"
6063
Focusable="False"
6164
KeyboardNavigation.TabIndex="1"
6265
Orientation="Horizontal" />
63-
</StackPanel>
64-
</ScrollViewer>
66+
</StackPanel>
67+
</ScrollViewer>
68+
69+
<!-- Wrapping headers -->
70+
<ScrollViewer x:Name="PART_HeaderWrapScrollViewer"
71+
HorizontalScrollBarVisibility="Disabled"
72+
VerticalScrollBarVisibility="Auto"
73+
Visibility="Collapsed">
74+
<WrapPanel x:Name="HeaderWrapPanel"
75+
Margin="{Binding Path=(wpf:TabAssist.HeaderPanelMargin), RelativeSource={RelativeSource TemplatedParent}}"
76+
Background="Transparent"
77+
IsItemsHost="True"
78+
KeyboardNavigation.TabIndex="1" />
79+
</ScrollViewer>
80+
</Grid>
6581
</wpf:ColorZone>
6682
<Border x:Name="PART_BorderSelectedContent"
67-
Padding="{TemplateBinding Padding}"
68-
HorizontalAlignment="Stretch"
69-
VerticalAlignment="Stretch"
70-
Panel.ZIndex="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Panel.ZIndex)}"
71-
Background="{x:Null}"
72-
Focusable="False">
83+
Padding="{TemplateBinding Padding}"
84+
HorizontalAlignment="Stretch"
85+
VerticalAlignment="Stretch"
86+
Panel.ZIndex="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(Panel.ZIndex)}"
87+
Background="{x:Null}"
88+
Focusable="False">
7389
<ContentPresenter x:Name="PART_SelectedContentHost"
74-
Margin="{TemplateBinding Padding}"
75-
ContentSource="SelectedContent"
76-
ContentStringFormat="{TemplateBinding SelectedContentStringFormat}"
77-
ContentTemplate="{TemplateBinding SelectedContentTemplate}"
78-
ContentTemplateSelector="{TemplateBinding SelectedContentTemplateSelector}"
79-
Focusable="False"
80-
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
90+
Margin="{TemplateBinding Padding}"
91+
ContentSource="SelectedContent"
92+
ContentStringFormat="{TemplateBinding SelectedContentStringFormat}"
93+
ContentTemplate="{TemplateBinding SelectedContentTemplate}"
94+
ContentTemplateSelector="{TemplateBinding SelectedContentTemplateSelector}"
95+
Focusable="False"
96+
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
8197
</Border>
8298
</DockPanel>
8399

84100
<ControlTemplate.Triggers>
101+
102+
<Trigger Property="wpf:TabAssist.HeaderBehavior" Value="Scrolling">
103+
<Setter TargetName="PART_HeaderScrollViewer" Property="Visibility" Value="Visible"/>
104+
<Setter TargetName="PART_HeaderWrapScrollViewer" Property="Visibility" Value="Collapsed"/>
105+
</Trigger>
106+
<Trigger Property="wpf:TabAssist.HeaderBehavior" Value="Wrapping">
107+
<Setter TargetName="PART_HeaderScrollViewer" Property="Visibility" Value="Collapsed"/>
108+
<Setter TargetName="PART_HeaderWrapScrollViewer" Property="Visibility" Value="Visible"/>
109+
</Trigger>
110+
85111
<Trigger Property="HorizontalContentAlignment" Value="Stretch">
86112
<Setter TargetName="CenteredHeaderPanel" Property="Visibility" Value="Visible" />
87113
<Setter TargetName="HeaderPanel" Property="Visibility" Value="Collapsed" />

0 commit comments

Comments
 (0)