Skip to content

Commit 0feca9c

Browse files
author
msftbot[bot]
authored
Add basic SwitchPresenter Sample (#3789)
## Also Fixes #3671, and related to #1908 Adds a basic sample for SwitchPresenter to the sample app. Would like to do a more advanced one still though. This also fixes a small bug in the case selection logic. _Any suggestions for sample scenarios where we could switch off a strong type like an enum or some other type would be appreciated._ 🙂 ## PR Type What kind of change does this PR introduce? <!-- Please uncomment one or more that apply to this PR. --> - Bugfix <!-- - Feature --> <!-- - Code style update (formatting) --> <!-- - Refactoring (no functional changes, no api changes) --> <!-- - Build or CI related changes --> <!-- - Documentation content changes --> - Sample app changes <!-- - Other... Please describe: --> ## What is the current behavior? Would crash if no default case provided and no matching case available. (And no sample.) ## What is the new behavior? Control goes back to presenting nothing if no match or default is available. + Sample! ## PR Checklist Please check if your PR fulfills the following requirements: - [ ] Tested code with current [supported SDKs](../readme.md#supported) - [ ] Pull Request has been submitted to the documentation repository [instructions](..\contributing.md#docs). Link: <!-- docs PR link --> - [ ] Sample in sample app has been added / updated (for bug fixes / features) - [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets) - [ ] New major technical changes in the toolkit have or will be added to the [Wiki](https://github.com/windows-toolkit/WindowsCommunityToolkit/wiki) e.g. build changes, source generators, testing infrastructure, sample creation changes, etc... - [ ] Tests for the changes have been added (for bug fixes / features) (if applicable) - [ ] Header has been added to all new source files (run *build/UpdateHeaders.bat*) - [ ] Contains **NO** breaking changes <!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. Please note that breaking changes are likely to be rejected within minor release cycles or held until major versions. --> ## TO DO - [x] Add an Advanced scenario to the page using TargetType - [x] Address #3784 as well? (Think un-needed for now?) App can always do this if needed. - [x] Remove listening for Child Value binding changes as complicates the control.
2 parents daa8869 + bb961a4 commit 0feca9c

File tree

11 files changed

+135
-187
lines changed

11 files changed

+135
-187
lines changed

Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@
272272
<Content Include="Icons\More.png" />
273273
<Content Include="Icons\Notifications.png" />
274274
<Content Include="Icons\Services.png" />
275+
<Content Include="SamplePages\Primitives\SwitchPresenter.png" />
275276
<Content Include="SamplePages\TabbedCommandBar\TabbedCommandBar.png" />
276277
<Content Include="SamplePages\Animations\Effects\FadeBehavior.png" />
277278
<Content Include="SamplePages\ColorPicker\ColorPicker.png" />
@@ -976,6 +977,9 @@
976977
<SubType>Designer</SubType>
977978
<Generator>MSBuild:Compile</Generator>
978979
</Page>
980+
<Content Include="SamplePages\Primitives\SwitchPresenter.bind">
981+
<SubType>Designer</SubType>
982+
</Content>
979983
<Page Include="SamplePages\TilesBrush\TilesBrushPage.xaml">
980984
<Generator>MSBuild:Compile</Generator>
981985
<SubType>Designer</SubType>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/Animal.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public enum Animal
99
Cat,
1010
Dog,
1111
Bunny,
12+
Llama,
1213
Parrot,
1314
Squirrel
1415
}

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/AnimalToColorConverter.xaml.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public object Convert(object value, Type targetType, object parameter, string la
1818
Animal.Cat => Colors.Coral,
1919
Animal.Dog => Colors.Gray,
2020
Animal.Bunny => Colors.Green,
21+
Animal.Llama => Colors.Beige,
2122
Animal.Parrot => Colors.YellowGreen,
2223
Animal.Squirrel => Colors.SaddleBrown,
2324
_ => throw new ArgumentException("Invalid value", nameof(value))
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<Page
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6+
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
7+
xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
8+
xmlns:enums="using:Microsoft.Toolkit.Uwp.SampleApp.Enums"
9+
mc:Ignorable="d">
10+
11+
<StackPanel Padding="16">
12+
<!-- Basic Sample -->
13+
<ComboBox x:Name="Lookup" Header="Look up reservation" SelectedIndex="0"
14+
Margin="0,0,0,8">
15+
<x:String>Select an option</x:String>
16+
<x:String>Confirmation Code</x:String>
17+
<x:String>E-ticket number</x:String>
18+
<x:String>Mileage Plan number</x:String>
19+
</ComboBox>
20+
<!-- SwitchPresenter binds to a value -->
21+
<controls:SwitchPresenter Value="{Binding SelectedItem, ElementName=Lookup}">
22+
<!-- And then only dynamically displays the Case with the matching Value -->
23+
<controls:Case Value="Confirmation Code">
24+
<StackPanel>
25+
<TextBox Name="ConfirmationCodeValidator"
26+
ui:TextBoxExtensions.Regex="^[a-zA-Z]{6}$"
27+
Header="Confirmation code"
28+
PlaceholderText="6 letters" />
29+
<TextBlock Visibility="{Binding (ui:TextBoxExtensions.IsValid), ElementName=ConfirmationCodeValidator}">Thanks for entering a valid code!</TextBlock>
30+
</StackPanel>
31+
</controls:Case>
32+
<controls:Case Value="E-ticket number">
33+
<StackPanel>
34+
<TextBox Name="TicketValidator"
35+
ui:TextBoxExtensions.Regex="(^\d{10}$)|(^\d{13}$)"
36+
Header="E-ticket number"
37+
PlaceholderText="10 or 13 numbers" />
38+
<TextBlock Visibility="{Binding (ui:TextBoxExtensions.IsValid), ElementName=TicketValidator}">Thanks for entering a valid code!</TextBlock>
39+
</StackPanel>
40+
</controls:Case>
41+
<controls:Case Value="Mileage Plan number">
42+
<TextBox Name="PlanValidator"
43+
Header="Mileage Plan #"
44+
PlaceholderText="Mileage Plan #" />
45+
</controls:Case>
46+
<!-- You can also provide a default case if no match is found -->
47+
<controls:Case IsDefault="True">
48+
<TextBlock>Please select a way to lookup your reservation above...</TextBlock>
49+
</controls:Case>
50+
</controls:SwitchPresenter>
51+
52+
<Border Height="2" Background="Gray" Margin="0,16"/>
53+
54+
<!-- Scenario using an Enum -->
55+
<ComboBox x:Name="AnimalPicker"
56+
Header="Pick an Animal"
57+
ItemsSource="{ui:EnumValues Type=enums:Animal}"
58+
SelectedIndex="0"/>
59+
<controls:SwitchPresenter Value="{Binding SelectedItem, ElementName=AnimalPicker}"
60+
TargetType="enums:Animal"
61+
Padding="16">
62+
<controls:Case Value="Cat">
63+
<TextBlock FontSize="32">🐈</TextBlock>
64+
</controls:Case>
65+
<controls:Case Value="Dog">
66+
<TextBlock FontSize="32">🐕</TextBlock>
67+
</controls:Case>
68+
<controls:Case Value="Bunny">
69+
<TextBlock FontSize="32">🐇</TextBlock>
70+
</controls:Case>
71+
<controls:Case Value="Llama">
72+
<TextBlock FontSize="32">🦙</TextBlock>
73+
</controls:Case>
74+
<controls:Case Value="Parrot">
75+
<TextBlock FontSize="32">🦜</TextBlock>
76+
</controls:Case>
77+
<controls:Case Value="Squirrel">
78+
<TextBlock FontSize="32">🐿</TextBlock>
79+
</controls:Case>
80+
</controls:SwitchPresenter>
81+
</StackPanel>
82+
</Page>
1.18 KB
Loading

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/WrapPanel/WrapPanel.bind

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,13 @@
3232
</Grid>
3333
</DataTemplate>
3434
<Style TargetType="ListViewItem">
35+
<!-- Change those values to change the WrapPanel's children alignment -->
36+
<Setter Property="VerticalContentAlignment" Value="Center" />
37+
<Setter Property="HorizontalContentAlignment" Value="Center" />
3538
<Setter Property="Margin" Value="0" />
3639
<Setter Property="Padding" Value="0" />
40+
<Setter Property="MinWidth" Value="0" />
41+
<Setter Property="MinHeight" Value="0" />
3742
</Style>
3843
</Page.Resources>
3944

@@ -49,16 +54,6 @@
4954
HorizontalSpacing="@[HorizontalSpacing:Slider:5:0-200]@" />
5055
</ItemsPanelTemplate>
5156
</ItemsControl.ItemsPanel>
52-
<ListView.ItemContainerStyle>
53-
<Style TargetType="ListViewItem">
54-
<!-- Change those values to change the WrapPanel's children alignment -->
55-
<Setter Property="VerticalContentAlignment" Value="Center" />
56-
<Setter Property="HorizontalContentAlignment" Value="Center" />
57-
<Setter Property="Padding" Value="0" />
58-
<Setter Property="MinWidth" Value="0" />
59-
<Setter Property="MinHeight" Value="0" />
60-
</Style>
61-
</ListView.ItemContainerStyle>
6257
</ListView>
6358
</Grid>
6459
</Page>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:ani="using:Microsoft.Toolkit.Uwp.UI.Animations"
55
xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
6+
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
67
xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
78
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
89
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
@@ -34,6 +35,11 @@
3435
<ui:SurfaceDialOptions />
3536
</ui:TextBoxExtensions.SurfaceDialOptions>
3637
</TextBox>
38+
<controls:SwitchPresenter x:Key="SwitchPresenterControl">
39+
<controls:CaseCollection>
40+
<controls:Case IsDefault="True" />
41+
</controls:CaseCollection>
42+
</controls:SwitchPresenter>
3743
</Page.Resources>
3844

3945
<Grid>

Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,15 @@
463463
"XamlCodeFile": "/SamplePages/TabbedCommandBar/TabbedCommandBar.bind",
464464
"Icon": "/SamplePages/TabbedCommandBar/TabbedCommandBar.png",
465465
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/TabbedCommandBar.md"
466+
},
467+
{
468+
"Name": "SwitchPresenter",
469+
"Subcategory": "Layout",
470+
"About": "The SwitchPresenter is a ContentPresenter which can allow a developer to mimic a switch statement within XAML.",
471+
"CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter",
472+
"XamlCodeFile": "/SamplePages/Primitives/SwitchPresenter.bind",
473+
"Icon": "/SamplePages/Primitives/SwitchPresenter.png",
474+
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/SwitchPresenter.md"
466475
}
467476
]
468477
},

Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/Case.cs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
1414
[ContentProperty(Name = nameof(Content))]
1515
public partial class Case : DependencyObject
1616
{
17-
internal SwitchPresenter Parent { get; set; } // TODO: Can we remove Parent need here and just use events?
18-
19-
/// <summary>
20-
/// Event raised when the <see cref="Value"/> property changes.
21-
/// </summary>
22-
public event EventHandler ValueChanged;
23-
2417
/// <summary>
2518
/// Gets or sets the Content to display when this case is active.
2619
/// </summary>
@@ -64,14 +57,7 @@ public object Value
6457
/// Identifies the <see cref="Value"/> property.
6558
/// </summary>
6659
public static readonly DependencyProperty ValueProperty =
67-
DependencyProperty.Register(nameof(Value), typeof(object), typeof(Case), new PropertyMetadata(null, OnValuePropertyChanged));
68-
69-
private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
70-
{
71-
var xcase = (Case)d;
72-
73-
xcase.ValueChanged?.Invoke(xcase, EventArgs.Empty);
74-
}
60+
DependencyProperty.Register(nameof(Value), typeof(object), typeof(Case), new PropertyMetadata(null));
7561

7662
/// <summary>
7763
/// Initializes a new instance of the <see cref="Case"/> class.

Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/CaseCollection.cs

Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -5,130 +5,20 @@
55
using System;
66
using System.Collections;
77
using System.Collections.Generic;
8+
using Windows.UI.Xaml;
89

910
namespace Microsoft.Toolkit.Uwp.UI.Controls
1011
{
1112
/// <summary>
1213
/// An collection of <see cref="Case"/> to help with XAML interop.
1314
/// </summary>
14-
public class CaseCollection : IList<Case>, IEnumerable<Case> // TODO: Do we need this or can we use an ObservableCollection directly??? (Or is it useful to have it manage the registration of the child events?)
15+
public class CaseCollection : DependencyObjectCollection
1516
{
16-
internal SwitchPresenter Parent { get; set; } // TODO: Can we remove Parent need here and just use events?
17-
18-
private readonly List<Case> _internalList = new List<Case>();
19-
20-
/// <inheritdoc/>
21-
public int Count => _internalList.Count;
22-
23-
/// <inheritdoc/>
24-
public bool IsReadOnly => false;
25-
26-
/// <inheritdoc/>
27-
public Case this[int index] { get => _internalList[index]; set => Insert(index, value); }
28-
29-
/// <summary>
30-
/// Raised when an animation has been added/removed or modified
31-
/// </summary>
32-
public event EventHandler CaseCollectionChanged;
33-
34-
private void ValueChanged(object sender, EventArgs e)
35-
{
36-
CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
37-
}
38-
3917
/// <summary>
4018
/// Initializes a new instance of the <see cref="CaseCollection"/> class.
4119
/// </summary>
4220
public CaseCollection()
4321
{
4422
}
45-
46-
/// <inheritdoc/>
47-
public int IndexOf(Case item)
48-
{
49-
return _internalList.IndexOf(item);
50-
}
51-
52-
/// <inheritdoc/>
53-
public void Insert(int index, Case item)
54-
{
55-
item.ValueChanged += ValueChanged;
56-
item.Parent = Parent;
57-
_internalList.Insert(index, item);
58-
CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
59-
}
60-
61-
/// <inheritdoc/>
62-
public void RemoveAt(int index)
63-
{
64-
if (index >= 0 && index < _internalList.Count)
65-
{
66-
var xcase = _internalList[index];
67-
xcase.ValueChanged -= ValueChanged;
68-
xcase.Parent = null;
69-
}
70-
71-
_internalList.RemoveAt(index);
72-
CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
73-
}
74-
75-
/// <inheritdoc/>
76-
public void Add(Case item)
77-
{
78-
item.ValueChanged += ValueChanged;
79-
item.Parent = Parent;
80-
_internalList.Add(item);
81-
CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
82-
}
83-
84-
/// <inheritdoc/>
85-
public void Clear()
86-
{
87-
foreach (var xcase in _internalList)
88-
{
89-
xcase.ValueChanged -= ValueChanged;
90-
xcase.Parent = null;
91-
}
92-
93-
_internalList.Clear();
94-
CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
95-
}
96-
97-
/// <inheritdoc/>
98-
public bool Contains(Case item)
99-
{
100-
return _internalList.Contains(item);
101-
}
102-
103-
/// <inheritdoc/>
104-
public void CopyTo(Case[] array, int arrayIndex)
105-
{
106-
_internalList.CopyTo(array, arrayIndex);
107-
}
108-
109-
/// <inheritdoc/>
110-
public bool Remove(Case item)
111-
{
112-
var result = _internalList.Remove(item);
113-
if (result)
114-
{
115-
item.ValueChanged -= ValueChanged;
116-
item.Parent = null;
117-
CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
118-
}
119-
120-
return result;
121-
}
122-
123-
/// <inheritdoc/>
124-
public IEnumerator<Case> GetEnumerator()
125-
{
126-
return _internalList.GetEnumerator();
127-
}
128-
129-
IEnumerator IEnumerable.GetEnumerator()
130-
{
131-
return _internalList.GetEnumerator();
132-
}
13323
}
13424
}

0 commit comments

Comments
 (0)