Skip to content

Commit c063978

Browse files
committed
feat: add orientation toggle and fix vertical mode layout issues
- Add orientation selector to RangeSelectorSample for testing both horizontal and vertical modes - Fix Canvas position property conflicts when switching between orientations by clearing old properties - Change default VerticalAlignment from Stretch to Top to prevent breaking existing horizontal layouts - Vertical mode explicitly sets VerticalAlignment="Stretch" via VisualState - This preserves backward compatibility for existing horizontal RangeSelector usage - Improve vertical mode visual states with explicit sizing and alignment setters for both orientations - Set visual state transition to non-animated (false) to prevent layout glitches during orientation changes - Update documentation with guidance on using VerticalAlignment="Stretch" for vertical orientation
1 parent 84cf65a commit c063978

File tree

6 files changed

+77
-7
lines changed

6 files changed

+77
-7
lines changed

components/RangeSelector/samples/RangeSelector.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,21 @@ A `RangeSelector` is pretty similar to a regular `Slider`, and shares some of it
1616

1717
> [!Sample RangeSelectorSample]
1818
19-
## Vertical Orientation
19+
> [!NOTE]
20+
> Use 'VerticalAlignment="Stretch"' When 'Orientation="Vertical"'
2021
21-
The `RangeSelector` also supports vertical orientation. Set the `Orientation` property to `Vertical` to display the range selector vertically.
22+
Like this:
2223

23-
> [!Sample RangeSelectorVerticalSample]
24+
```xaml
25+
<controls:RangeSelector x:Name="rangeSelector"
26+
VerticalAlignment="Stretch"
27+
Maximum="100"
28+
Minimum="1"
29+
Orientation="Vertical"
30+
RangeEnd="100"
31+
RangeStart="0"
32+
StepFrequency="1" />
33+
```
2434

2535
> [!NOTE]
2636
> If you are using a RangeSelector within a ScrollViewer you'll need to add some codes. This is because by default, the ScrollViewer will block the thumbs of the RangeSelector to capture the pointer.

components/RangeSelector/samples/RangeSelectorSample.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
MinHeight="86"
1313
MaxWidth="560"
1414
HorizontalAlignment="Stretch">
15+
<!-- Use 'VerticalAlignment="Stretch"' When 'Orientation="Vertical"' -->
1516
<controls:RangeSelector x:Name="rangeSelector"
1617
VerticalAlignment="Center"
1718
IsEnabled="{x:Bind Enable, Mode=OneWay}"
1819
Maximum="{x:Bind Maximum, Mode=OneWay}"
1920
Minimum="{x:Bind Minimum, Mode=OneWay}"
21+
Orientation="{x:Bind OrientationMode, Mode=OneWay}"
2022
RangeEnd="100"
2123
RangeStart="0"
2224
StepFrequency="{x:Bind StepFrequency, Mode=OneWay}" />

components/RangeSelector/samples/RangeSelectorSample.xaml.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace RangeSelectorExperiment.Samples;
99
[ToolkitSampleNumericOption("Minimum", 0, 0, 100, 1, false, Title = "Minimum")]
1010
[ToolkitSampleNumericOption("Maximum", 100, 0, 100, 1, false, Title = "Maximum")]
1111
[ToolkitSampleNumericOption("StepFrequency", 1, 0, 10, 1, false, Title = "StepFrequency")]
12+
[ToolkitSampleMultiChoiceOption("OrientationMode", "Horizontal", "Vertical", Title = "Orientation")]
1213
[ToolkitSampleBoolOption("Enable", true, Title = "IsEnabled")]
1314

1415
[ToolkitSample(id: nameof(RangeSelectorSample), "RangeSelector", description: $"A sample for showing how to create and use a {nameof(RangeSelector)} control.")]

components/RangeSelector/src/RangeSelector.Properties.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,29 @@ private static void OrientationChangedCallback(DependencyObject d, DependencyPro
173173
return;
174174
}
175175

176-
VisualStateManager.GoToState(rangeSelector, rangeSelector.Orientation == Orientation.Horizontal ? HorizontalState : VerticalState, true);
176+
// Clear old Canvas position properties before switching orientation
177+
if (rangeSelector._minThumb != null && rangeSelector._maxThumb != null && rangeSelector._activeRectangle != null)
178+
{
179+
var oldOrientation = (Orientation)e.OldValue;
180+
var newOrientation = (Orientation)e.NewValue;
181+
182+
if (oldOrientation == Orientation.Horizontal && newOrientation == Orientation.Vertical)
183+
{
184+
// Clear horizontal properties
185+
rangeSelector._minThumb.ClearValue(Canvas.LeftProperty);
186+
rangeSelector._maxThumb.ClearValue(Canvas.LeftProperty);
187+
rangeSelector._activeRectangle.ClearValue(Canvas.LeftProperty);
188+
}
189+
else if (oldOrientation == Orientation.Vertical && newOrientation == Orientation.Horizontal)
190+
{
191+
// Clear vertical properties
192+
rangeSelector._minThumb.ClearValue(Canvas.TopProperty);
193+
rangeSelector._maxThumb.ClearValue(Canvas.TopProperty);
194+
rangeSelector._activeRectangle.ClearValue(Canvas.TopProperty);
195+
}
196+
}
197+
198+
VisualStateManager.GoToState(rangeSelector, rangeSelector.Orientation == Orientation.Horizontal ? HorizontalState : VerticalState, false);
177199

178200
rangeSelector.SyncThumbs();
179201
}

components/RangeSelector/src/RangeSelector.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,23 @@ private void SyncThumbs(bool fromMinKeyDown = false, bool fromMaxKeyDown = false
264264

265265
if (isHorizontal)
266266
{
267+
// Set horizontal positions
267268
Canvas.SetLeft(_minThumb, relativeStart);
268269
Canvas.SetLeft(_maxThumb, relativeEnd);
270+
271+
// Clear vertical positions to prevent conflicts
272+
_minThumb.ClearValue(Canvas.TopProperty);
273+
_maxThumb.ClearValue(Canvas.TopProperty);
269274
}
270275
else
271276
{
272277
// Vertical: invert positions so min is at bottom, max is at top
273278
Canvas.SetTop(_minThumb, DragWidth() - relativeStart);
274279
Canvas.SetTop(_maxThumb, DragWidth() - relativeEnd);
280+
281+
// Clear horizontal positions to prevent conflicts
282+
_minThumb.ClearValue(Canvas.LeftProperty);
283+
_maxThumb.ClearValue(Canvas.LeftProperty);
275284
}
276285

277286
if (fromMinKeyDown || fromMaxKeyDown)

components/RangeSelector/src/RangeSelector.xaml

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@
1010
<Style BasedOn="{StaticResource DefaultRangeSelectorStyle}"
1111
TargetType="controls:RangeSelector" />
1212

13+
<x:Double x:Key="RangeSelectorVerticalMinHeight">150</x:Double>
14+
<x:Double x:Key="RangeSelectorVerticalMinWidth">32</x:Double>
15+
16+
1317
<Style x:Key="DefaultRangeSelectorStyle"
1418
TargetType="controls:RangeSelector">
1519
<Setter Property="Background" Value="{ThemeResource SliderTrackFill}" />
1620
<Setter Property="BorderThickness" Value="{ThemeResource SliderBorderThemeThickness}" />
1721
<Setter Property="Foreground" Value="{ThemeResource SliderTrackValueFill}" />
1822
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
1923
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
20-
<Setter Property="HorizontalAlignment" Value="Stretch" />
21-
<Setter Property="VerticalAlignment" Value="Stretch" />
24+
<Setter Property="VerticalAlignment" Value="Top" />
2225
<Setter Property="CornerRadius" Value="{ThemeResource SliderTrackCornerRadius}" />
2326
<Setter Property="Template">
2427
<Setter.Value>
@@ -248,11 +251,34 @@
248251
</VisualState>
249252
</VisualStateGroup>
250253
<VisualStateGroup x:Name="OrientationStates">
251-
<VisualState x:Name="Horizontal" />
254+
<VisualState x:Name="Horizontal">
255+
<VisualState.Setters>
256+
<Setter Target="ControlGrid.Height" Value="{ThemeResource SliderHorizontalHeight}" />
257+
<Setter Target="ControlGrid.Width" Value="Auto" />
258+
<Setter Target="ControlGrid.MinHeight" Value="0" />
259+
<Setter Target="ControlGrid.MinWidth" Value="0" />
260+
<Setter Target="ControlGrid.VerticalAlignment" Value="Top" />
261+
<Setter Target="ControlGrid.HorizontalAlignment" Value="Stretch" />
262+
<Setter Target="BackgroundElement.Height" Value="4" />
263+
<Setter Target="BackgroundElement.Width" Value="Auto" />
264+
<Setter Target="ActiveRectangle.Height" Value="4" />
265+
<Setter Target="MinThumb.Margin" Value="0,7,0,0" />
266+
<Setter Target="MinThumb.HorizontalAlignment" Value="Left" />
267+
<Setter Target="MinThumb.VerticalAlignment" Value="Center" />
268+
<Setter Target="MaxThumb.Margin" Value="0,7,0,0" />
269+
<Setter Target="MaxThumb.HorizontalAlignment" Value="Left" />
270+
<Setter Target="MaxThumb.VerticalAlignment" Value="Center" />
271+
<Setter Target="ToolTip.Margin" Value="0,-52,0,16" />
272+
</VisualState.Setters>
273+
</VisualState>
252274
<VisualState x:Name="Vertical">
253275
<VisualState.Setters>
254276
<Setter Target="ControlGrid.Height" Value="Auto" />
255277
<Setter Target="ControlGrid.Width" Value="{ThemeResource SliderHorizontalHeight}" />
278+
<Setter Target="ControlGrid.MinHeight" Value="{StaticResource RangeSelectorVerticalMinHeight}" />
279+
<Setter Target="ControlGrid.MinWidth" Value="{StaticResource RangeSelectorVerticalMinWidth}" />
280+
<Setter Target="ControlGrid.VerticalAlignment" Value="Stretch" />
281+
<Setter Target="ControlGrid.HorizontalAlignment" Value="Center" />
256282
<Setter Target="BackgroundElement.Height" Value="Auto" />
257283
<Setter Target="BackgroundElement.Width" Value="4" />
258284
<Setter Target="ActiveRectangle.Width" Value="4" />

0 commit comments

Comments
 (0)