Skip to content

Commit 4d35ca1

Browse files
committed
Added orientation to default Segmented style
1 parent 25106dc commit 4d35ca1

File tree

7 files changed

+121
-45
lines changed

7 files changed

+121
-45
lines changed

components/Segmented/samples/SegmentedBasicSample.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<TextBlock Style="{StaticResource BodyStrongTextBlockStyle}"
1515
Text="Icon + content" />
1616
<controls:Segmented HorizontalAlignment="{x:Bind local:SegmentedBasicSample.ConvertStringToHorizontalAlignment(Alignment), Mode=OneWay}"
17+
Orientation="{x:Bind local:SegmentedBasicSample.ConvertStringToOrientation(OrientationMode), Mode=OneWay}"
1718
SelectedIndex="0"
1819
SelectionMode="{x:Bind local:SegmentedBasicSample.ConvertStringToSelectionMode(SelectionMode), Mode=OneWay}">
1920
<controls:SegmentedItem Content="Item 1"
@@ -30,6 +31,7 @@
3031
Style="{StaticResource BodyStrongTextBlockStyle}"
3132
Text="Icon only" />
3233
<controls:Segmented HorizontalAlignment="{x:Bind local:SegmentedBasicSample.ConvertStringToHorizontalAlignment(Alignment), Mode=OneWay}"
34+
Orientation="{x:Bind local:SegmentedBasicSample.ConvertStringToOrientation(OrientationMode), Mode=OneWay}"
3335
SelectedIndex="2"
3436
SelectionMode="{x:Bind local:SegmentedBasicSample.ConvertStringToSelectionMode(SelectionMode), Mode=OneWay}">
3537
<controls:SegmentedItem Icon="{ui:FontIcon Glyph=&#xE8BF;}"

components/Segmented/samples/SegmentedBasicSample.xaml.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace SegmentedExperiment.Samples;
1111
/// </summary>
1212
[ToolkitSampleMultiChoiceOption("SelectionMode", "Single", "Multiple", Title = "Selection mode")]
1313
[ToolkitSampleMultiChoiceOption("Alignment", "Left", "Center", "Right", "Stretch", Title = "Horizontal alignment")]
14+
[ToolkitSampleMultiChoiceOption("OrientationMode", "Horizontal", "Vertical", Title = "Orientation")]
1415

1516
[ToolkitSample(id: nameof(SegmentedBasicSample), "Basics", description: $"A sample for showing how to create and use a {nameof(Segmented)} custom control.")]
1617
public sealed partial class SegmentedBasicSample : Page
@@ -36,5 +37,12 @@ public SegmentedBasicSample()
3637
"Stretch" => HorizontalAlignment.Stretch,
3738
_ => throw new System.NotImplementedException(),
3839
};
40+
41+
public static Orientation ConvertStringToOrientation(string orientation) => orientation switch
42+
{
43+
"Horizontal" => Orientation.Horizontal,
44+
"Vertical" => Orientation.Vertical,
45+
_ => throw new System.NotImplementedException(),
46+
};
3947
}
4048

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace CommunityToolkit.WinUI.Controls;
6+
7+
public partial class Segmented
8+
{
9+
/// <summary>
10+
/// The backing <see cref="DependencyProperty"/> for the <see cref="Orientation"/> property.
11+
/// </summary>
12+
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
13+
nameof(Orientation),
14+
typeof(Orientation),
15+
typeof(Segmented),
16+
new PropertyMetadata(Orientation.Horizontal, (d, e) => ((Segmented)d).OnOrientationChanged()));
17+
18+
/// <summary>
19+
/// Gets or sets the orientation.
20+
/// </summary>
21+
public Orientation Orientation
22+
{
23+
get => (Orientation)GetValue(OrientationProperty);
24+
set => SetValue(OrientationProperty, value);
25+
}
26+
}

components/Segmented/src/Segmented/Segmented.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public Segmented()
2222
this.DefaultStyleKey = typeof(Segmented);
2323

2424
RegisterPropertyChangedCallback(SelectedIndexProperty, OnSelectedIndexChanged);
25+
RegisterPropertyChangedCallback(OrientationProperty, OnSelectedIndexChanged);
2526
}
2627

2728
/// <inheritdoc/>
@@ -154,4 +155,16 @@ private void OnSelectedIndexChanged(DependencyObject sender, DependencyProperty
154155
_internalSelectedIndex = SelectedIndex;
155156
}
156157
}
158+
159+
private void OnOrientationChanged()
160+
{
161+
for (int i = 0; i < Items.Count; i++)
162+
{
163+
var container = ContainerFromIndex(i) as SegmentedItem;
164+
if (container is null)
165+
continue;
166+
167+
container.UpdateOrientation(Orientation);
168+
}
169+
}
157170
}

components/Segmented/src/Segmented/Segmented.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
<ItemsPanelTemplate>
5959
<local:EqualPanel HorizontalAlignment="{Binding (tk:FrameworkElementExtensions.Ancestor).HorizontalAlignment, RelativeSource={RelativeSource Self}}"
6060
tk:FrameworkElementExtensions.AncestorType="local:Segmented"
61+
Orientation="{Binding (tk:FrameworkElementExtensions.Ancestor).Orientation, RelativeSource={RelativeSource Self}}"
6162
Spacing="{ThemeResource SegmentedItemSpacing}" />
6263
</ItemsPanelTemplate>
6364
</Setter.Value>
@@ -111,7 +112,7 @@
111112
<Setter Property="ItemsPanel">
112113
<Setter.Value>
113114
<ItemsPanelTemplate>
114-
<StackPanel Orientation="Horizontal"
115+
<StackPanel Orientation="{Binding (tk:FrameworkElementExtensions.Ancestor).Orientation, RelativeSource={RelativeSource Self}}"
115116
Spacing="{ThemeResource ButtonItemSpacing}" />
116117
</ItemsPanelTemplate>
117118
</Setter.Value>

components/Segmented/src/SegmentedItem/SegmentedItem.cs

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using Windows.Media.Devices;
6+
57
namespace CommunityToolkit.WinUI.Controls;
68

79
/// <summary>
@@ -11,9 +13,15 @@ namespace CommunityToolkit.WinUI.Controls;
1113
public partial class SegmentedItem : ListViewItem
1214
{
1315
internal const string IconLeftState = "IconLeft";
16+
internal const string IconTopState = "IconTop";
1417
internal const string IconOnlyState = "IconOnly";
1518
internal const string ContentOnlyState = "ContentOnly";
1619

20+
internal const string HorizontalState = "Horizontal";
21+
internal const string VerticalState = "Vertical";
22+
23+
private bool _isVertical = false;
24+
1725
/// <summary>
1826
/// Creates a new instance of <see cref="SegmentedItem"/>.
1927
/// </summary>
@@ -26,8 +34,7 @@ public SegmentedItem()
2634
protected override void OnApplyTemplate()
2735
{
2836
base.OnApplyTemplate();
29-
OnIconChanged();
30-
ContentChanged();
37+
UpdateState();
3138
}
3239

3340
/// <summary>
@@ -36,38 +43,32 @@ protected override void OnApplyTemplate()
3643
protected override void OnContentChanged(object oldContent, object newContent)
3744
{
3845
base.OnContentChanged(oldContent, newContent);
39-
ContentChanged();
40-
}
41-
42-
private void ContentChanged()
43-
{
44-
if (Content != null)
45-
{
46-
VisualStateManager.GoToState(this, IconLeftState, true);
47-
}
48-
else
49-
{
50-
VisualStateManager.GoToState(this, IconOnlyState, true);
51-
}
46+
UpdateState();
5247
}
5348

5449
/// <summary>
5550
/// Handles changes to the Icon property.
5651
/// </summary>
57-
protected virtual void OnIconPropertyChanged(IconElement oldValue, IconElement newValue)
52+
protected virtual void OnIconPropertyChanged(IconElement oldValue, IconElement newValue) => UpdateState();
53+
54+
internal void UpdateOrientation(Orientation orientation)
5855
{
59-
OnIconChanged();
56+
_isVertical = orientation is Orientation.Vertical;
57+
UpdateState();
6058
}
6159

62-
private void OnIconChanged()
60+
private void UpdateState()
6361
{
64-
if (Icon != null)
62+
string contentState = (Icon is null, Content is null) switch
6563
{
66-
VisualStateManager.GoToState(this, IconLeftState, true);
67-
}
68-
else
69-
{
70-
VisualStateManager.GoToState(this, ContentOnlyState, true);
71-
}
64+
(false, false) => _isVertical ? IconTopState : IconLeftState,
65+
(false, true) => IconOnlyState,
66+
(true, false) => ContentOnlyState,
67+
(true, true) => ContentOnlyState, // Invalid state. Treast as content only
68+
};
69+
70+
// Update states
71+
VisualStateManager.GoToState(this, contentState, true);
72+
VisualStateManager.GoToState(this, _isVertical ? VerticalState : HorizontalState, true);
7273
}
7374
}

components/Segmented/src/SegmentedItem/SegmentedItem.xaml

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
1+
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:local="using:CommunityToolkit.WinUI.Controls"
44
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
@@ -405,12 +405,33 @@
405405
<win:BrushTransition Duration="0:0:0.083" />
406406
</win:Grid.BackgroundTransition>
407407
<VisualStateManager.VisualStateGroups>
408+
<VisualStateGroup x:Name="SegmentedOrientationStates">
409+
<VisualState x:Name="Horizontal" />
410+
<VisualState x:Name="Vertical">
411+
<VisualState.Setters>
412+
<Setter Target="PART_Pill.HorizontalAlignment" Value="Left" />
413+
<Setter Target="PART_Pill.VerticalAlignment" Value="Center" />
414+
<Setter Target="PART_Pill.(UIElement.RenderTransform).(CompositeTransform.Rotation)" Value="90" />
415+
</VisualState.Setters>
416+
</VisualState>
417+
</VisualStateGroup>
408418
<VisualStateGroup x:Name="SegmentedIconPositionStates">
409-
<VisualState x:Name="IconOnLeft" />
419+
<VisualState x:Name="IconLeft" />
420+
<VisualState x:Name="IconTop">
421+
<VisualState.Setters>
422+
<Setter Target="ContentHolder.ColumnSpacing" Value="0" />
423+
<Setter Target="ContentHolder.MaxWidth" Value="64" />
424+
<Setter Target="PART_IconBox.Width" Value="20" />
425+
<Setter Target="PART_IconBox.HorizontalAlignment" Value="Center" />
426+
<Setter Target="PART_ContentPresenter.(Grid.Column)" Value="0" />
427+
<Setter Target="PART_ContentPresenter.(Grid.Row)" Value="1" />
428+
<Setter Target="PART_ContentPresenter.MaxWidth" Value="48" />
429+
<Setter Target="PART_ContentPresenter.HorizontalAlignment" Value="Center" />
430+
</VisualState.Setters>
431+
</VisualState>
410432
<VisualState x:Name="IconOnly">
411433
<VisualState.Setters>
412434
<Setter Target="PART_ContentPresenter.Visibility" Value="Collapsed" />
413-
<Setter Target="PART_Pill.(Grid.Column)" Value="0" />
414435
<Setter Target="ContentHolder.ColumnSpacing" Value="0" />
415436
</VisualState.Setters>
416437
</VisualState>
@@ -634,6 +655,10 @@
634655
<ColumnDefinition Width="Auto" />
635656
<ColumnDefinition Width="Auto" />
636657
</Grid.ColumnDefinitions>
658+
<Grid.RowDefinitions>
659+
<RowDefinition Height="Auto" />
660+
<RowDefinition Height="Auto" />
661+
</Grid.RowDefinitions>
637662
<Viewbox x:Name="PART_IconBox"
638663
Width="16"
639664
Margin="0,7,0,7"
@@ -655,23 +680,23 @@
655680
ContentTransitions="{TemplateBinding ContentTransitions}"
656681
FontWeight="{TemplateBinding FontWeight}"
657682
Foreground="{TemplateBinding Foreground}" />
658-
<Rectangle x:Name="PART_Pill"
659-
Grid.Column="1"
660-
Width="4"
661-
Height="3"
662-
HorizontalAlignment="Center"
663-
VerticalAlignment="Bottom"
664-
Fill="{ThemeResource SegmentedPillBackground}"
665-
Opacity="0"
666-
RadiusX="0.5"
667-
RadiusY="1"
668-
RenderTransformOrigin="0.5, 0.5">
669-
<Rectangle.RenderTransform>
670-
<CompositeTransform x:Name="PillTransform"
671-
ScaleX="1" />
672-
</Rectangle.RenderTransform>
673-
</Rectangle>
674683
</Grid>
684+
685+
<Rectangle x:Name="PART_Pill"
686+
Width="4"
687+
Height="3"
688+
HorizontalAlignment="Center"
689+
VerticalAlignment="Bottom"
690+
Fill="{ThemeResource SegmentedPillBackground}"
691+
Opacity="0"
692+
RadiusX="0.5"
693+
RadiusY="1"
694+
RenderTransformOrigin="0.5, 0">
695+
<Rectangle.RenderTransform>
696+
<CompositeTransform x:Name="PillTransform"
697+
ScaleX="1" />
698+
</Rectangle.RenderTransform>
699+
</Rectangle>
675700
</Grid>
676701
</ControlTemplate>
677702
</Setter.Value>

0 commit comments

Comments
 (0)