Skip to content

Commit 24309cb

Browse files
committed
Added orientation to default Segmented style
1 parent 25106dc commit 24309cb

File tree

7 files changed

+122
-46
lines changed

7 files changed

+122
-46
lines changed

components/Segmented/samples/SegmentedBasicSample.xaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
1+
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
22
<Page x:Class="SegmentedExperiment.Samples.SegmentedBasicSample"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -15,6 +15,7 @@
1515
Text="Icon + content" />
1616
<controls:Segmented HorizontalAlignment="{x:Bind local:SegmentedBasicSample.ConvertStringToHorizontalAlignment(Alignment), Mode=OneWay}"
1717
SelectedIndex="0"
18+
Orientation="{x:Bind local:SegmentedBasicSample.ConvertStringToOrientation(OrientationMode), Mode=OneWay}"
1819
SelectionMode="{x:Bind local:SegmentedBasicSample.ConvertStringToSelectionMode(SelectionMode), Mode=OneWay}">
1920
<controls:SegmentedItem Content="Item 1"
2021
Icon="{ui:FontIcon Glyph=&#xEA3A;}" />
@@ -31,6 +32,7 @@
3132
Text="Icon only" />
3233
<controls:Segmented HorizontalAlignment="{x:Bind local:SegmentedBasicSample.ConvertStringToHorizontalAlignment(Alignment), Mode=OneWay}"
3334
SelectedIndex="2"
35+
Orientation="{x:Bind local:SegmentedBasicSample.ConvertStringToOrientation(OrientationMode), Mode=OneWay}"
3436
SelectionMode="{x:Bind local:SegmentedBasicSample.ConvertStringToSelectionMode(SelectionMode), Mode=OneWay}">
3537
<controls:SegmentedItem Icon="{ui:FontIcon Glyph=&#xE8BF;}"
3638
ToolTipService.ToolTip="Day view" />

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: 3 additions & 2 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:tk="using:CommunityToolkit.WinUI"
@@ -57,6 +57,7 @@
5757
<Setter.Value>
5858
<ItemsPanelTemplate>
5959
<local:EqualPanel HorizontalAlignment="{Binding (tk:FrameworkElementExtensions.Ancestor).HorizontalAlignment, RelativeSource={RelativeSource Self}}"
60+
Orientation="{Binding (tk:FrameworkElementExtensions.Ancestor).Orientation, RelativeSource={RelativeSource Self}}"
6061
tk:FrameworkElementExtensions.AncestorType="local:Segmented"
6162
Spacing="{ThemeResource SegmentedItemSpacing}" />
6263
</ItemsPanelTemplate>
@@ -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: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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)