diff --git a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
index 32dda221dcb..a6c0d8c7e51 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
+++ b/Microsoft.Toolkit.Uwp.SampleApp/Microsoft.Toolkit.Uwp.SampleApp.csproj
@@ -272,6 +272,7 @@
+
@@ -976,6 +977,9 @@
Designer
MSBuild:Compile
+
+ Designer
+
MSBuild:Compile
Designer
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/Animal.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/Animal.cs
index 2cf8d744e6c..166c1d4791e 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/Animal.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/Animal.cs
@@ -9,6 +9,7 @@ public enum Animal
Cat,
Dog,
Bunny,
+ Llama,
Parrot,
Squirrel
}
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/AnimalToColorConverter.xaml.cs b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/AnimalToColorConverter.xaml.cs
index 0b3cf01b79c..a681c092e75 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/AnimalToColorConverter.xaml.cs
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/EnumValuesExtension/AnimalToColorConverter.xaml.cs
@@ -18,6 +18,7 @@ public object Convert(object value, Type targetType, object parameter, string la
Animal.Cat => Colors.Coral,
Animal.Dog => Colors.Gray,
Animal.Bunny => Colors.Green,
+ Animal.Llama => Colors.Beige,
Animal.Parrot => Colors.YellowGreen,
Animal.Squirrel => Colors.SaddleBrown,
_ => throw new ArgumentException("Invalid value", nameof(value))
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Primitives/SwitchPresenter.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Primitives/SwitchPresenter.bind
new file mode 100644
index 00000000000..26e73185dfe
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Primitives/SwitchPresenter.bind
@@ -0,0 +1,82 @@
+
+
+
+
+
+ Select an option
+ Confirmation Code
+ E-ticket number
+ Mileage Plan number
+
+
+
+
+
+
+
+ Thanks for entering a valid code!
+
+
+
+
+
+ Thanks for entering a valid code!
+
+
+
+
+
+
+
+ Please select a way to lookup your reservation above...
+
+
+
+
+
+
+
+
+
+ 🐈
+
+
+ 🐕
+
+
+ 🐇
+
+
+ 🦙
+
+
+ 🦜
+
+
+ 🐿
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Primitives/SwitchPresenter.png b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Primitives/SwitchPresenter.png
new file mode 100644
index 00000000000..16ae1b91887
Binary files /dev/null and b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/Primitives/SwitchPresenter.png differ
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/WrapPanel/WrapPanel.bind b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/WrapPanel/WrapPanel.bind
index bb3f26c22d7..bd338f55473 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/WrapPanel/WrapPanel.bind
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/WrapPanel/WrapPanel.bind
@@ -32,8 +32,13 @@
@@ -49,16 +54,6 @@
HorizontalSpacing="@[HorizontalSpacing:Slider:5:0-200]@" />
-
-
-
\ No newline at end of file
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
index dee42559784..8577def2b8d 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/XamlOnlyPage.xaml
@@ -3,6 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ani="using:Microsoft.Toolkit.Uwp.UI.Animations"
xmlns:behaviors="using:Microsoft.Toolkit.Uwp.UI.Behaviors"
+ xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
@@ -34,6 +35,11 @@
+
+
+
+
+
diff --git a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
index f5a819be31a..826637d36e2 100644
--- a/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
+++ b/Microsoft.Toolkit.Uwp.SampleApp/SamplePages/samples.json
@@ -463,6 +463,15 @@
"XamlCodeFile": "/SamplePages/TabbedCommandBar/TabbedCommandBar.bind",
"Icon": "/SamplePages/TabbedCommandBar/TabbedCommandBar.png",
"DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/TabbedCommandBar.md"
+ },
+ {
+ "Name": "SwitchPresenter",
+ "Subcategory": "Layout",
+ "About": "The SwitchPresenter is a ContentPresenter which can allow a developer to mimic a switch statement within XAML.",
+ "CodeUrl": "https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter",
+ "XamlCodeFile": "/SamplePages/Primitives/SwitchPresenter.bind",
+ "Icon": "/SamplePages/Primitives/SwitchPresenter.png",
+ "DocumentationUrl": "https://raw.githubusercontent.com/MicrosoftDocs/WindowsCommunityToolkitDocs/master/docs/controls/SwitchPresenter.md"
}
]
},
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/Case.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/Case.cs
index 7829abc2a8f..bc7073d9ab5 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/Case.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/Case.cs
@@ -14,13 +14,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
[ContentProperty(Name = nameof(Content))]
public partial class Case : DependencyObject
{
- internal SwitchPresenter Parent { get; set; } // TODO: Can we remove Parent need here and just use events?
-
- ///
- /// Event raised when the property changes.
- ///
- public event EventHandler ValueChanged;
-
///
/// Gets or sets the Content to display when this case is active.
///
@@ -64,14 +57,7 @@ public object Value
/// Identifies the property.
///
public static readonly DependencyProperty ValueProperty =
- DependencyProperty.Register(nameof(Value), typeof(object), typeof(Case), new PropertyMetadata(null, OnValuePropertyChanged));
-
- private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var xcase = (Case)d;
-
- xcase.ValueChanged?.Invoke(xcase, EventArgs.Empty);
- }
+ DependencyProperty.Register(nameof(Value), typeof(object), typeof(Case), new PropertyMetadata(null));
///
/// Initializes a new instance of the class.
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/CaseCollection.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/CaseCollection.cs
index d1f3ee96187..42c8a9f7e80 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/CaseCollection.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/CaseCollection.cs
@@ -5,130 +5,20 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using Windows.UI.Xaml;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
///
/// An collection of to help with XAML interop.
///
- public class CaseCollection : IList, IEnumerable // 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?)
+ public class CaseCollection : DependencyObjectCollection
{
- internal SwitchPresenter Parent { get; set; } // TODO: Can we remove Parent need here and just use events?
-
- private readonly List _internalList = new List();
-
- ///
- public int Count => _internalList.Count;
-
- ///
- public bool IsReadOnly => false;
-
- ///
- public Case this[int index] { get => _internalList[index]; set => Insert(index, value); }
-
- ///
- /// Raised when an animation has been added/removed or modified
- ///
- public event EventHandler CaseCollectionChanged;
-
- private void ValueChanged(object sender, EventArgs e)
- {
- CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
- }
-
///
/// Initializes a new instance of the class.
///
public CaseCollection()
{
}
-
- ///
- public int IndexOf(Case item)
- {
- return _internalList.IndexOf(item);
- }
-
- ///
- public void Insert(int index, Case item)
- {
- item.ValueChanged += ValueChanged;
- item.Parent = Parent;
- _internalList.Insert(index, item);
- CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
- }
-
- ///
- public void RemoveAt(int index)
- {
- if (index >= 0 && index < _internalList.Count)
- {
- var xcase = _internalList[index];
- xcase.ValueChanged -= ValueChanged;
- xcase.Parent = null;
- }
-
- _internalList.RemoveAt(index);
- CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
- }
-
- ///
- public void Add(Case item)
- {
- item.ValueChanged += ValueChanged;
- item.Parent = Parent;
- _internalList.Add(item);
- CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
- }
-
- ///
- public void Clear()
- {
- foreach (var xcase in _internalList)
- {
- xcase.ValueChanged -= ValueChanged;
- xcase.Parent = null;
- }
-
- _internalList.Clear();
- CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
- }
-
- ///
- public bool Contains(Case item)
- {
- return _internalList.Contains(item);
- }
-
- ///
- public void CopyTo(Case[] array, int arrayIndex)
- {
- _internalList.CopyTo(array, arrayIndex);
- }
-
- ///
- public bool Remove(Case item)
- {
- var result = _internalList.Remove(item);
- if (result)
- {
- item.ValueChanged -= ValueChanged;
- item.Parent = null;
- CaseCollectionChanged?.Invoke(this, EventArgs.Empty);
- }
-
- return result;
- }
-
- ///
- public IEnumerator GetEnumerator()
- {
- return _internalList.GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return _internalList.GetEnumerator();
- }
}
}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/SwitchPresenter.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/SwitchPresenter.cs
index 0d1202e0bb7..c977b1b3681 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/SwitchPresenter.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Primitives/SwitchPresenter/SwitchPresenter.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.ComponentModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup;
@@ -45,7 +46,7 @@ public CaseCollection SwitchCases
/// Indicates the property.
///
public static readonly DependencyProperty SwitchCasesProperty =
- DependencyProperty.Register(nameof(SwitchCases), typeof(CaseCollection), typeof(SwitchPresenter), new PropertyMetadata(null, new PropertyChangedCallback(OnSwitchCasesPropertyChanged)));
+ DependencyProperty.Register(nameof(SwitchCases), typeof(CaseCollection), typeof(SwitchPresenter), new PropertyMetadata(null));
///
/// Gets or sets a value indicating the value to compare all cases against. When this value is bound to and changes, the presenter will automatically evaluate cases and select the new appropriate content from the switch.
@@ -60,48 +61,23 @@ public object Value
/// Indicates the property.
///
public static readonly DependencyProperty ValueProperty =
- DependencyProperty.Register(nameof(Value), typeof(object), typeof(SwitchPresenter), new PropertyMetadata(null, new PropertyChangedCallback(OnValuePropertyChanged)));
+ DependencyProperty.Register(nameof(Value), typeof(object), typeof(SwitchPresenter), new PropertyMetadata(null, OnValuePropertyChanged));
///
/// Gets or sets a value indicating which type to first cast and compare provided values against.
///
public Type TargetType
{
- get { return (Type)GetValue(DataTypeProperty); }
- set { SetValue(DataTypeProperty, value); }
+ get { return (Type)GetValue(TargetTypeProperty); }
+ set { SetValue(TargetTypeProperty, value); }
}
///
/// Indicates the property.
///
- public static readonly DependencyProperty DataTypeProperty =
+ public static readonly DependencyProperty TargetTypeProperty =
DependencyProperty.Register(nameof(TargetType), typeof(Type), typeof(SwitchPresenter), new PropertyMetadata(null));
- ///
- /// Gets or sets a value indicating whether the content is removed from the visual tree when switching between cases.
- ///
- public bool IsVisualTreeDisconnectedOnChange { get; set; }
-
- private static void OnSwitchCasesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (e.OldValue != null)
- {
- ((SwitchPresenter)e.OldValue).SwitchCases.CaseCollectionChanged -= OnCaseValuePropertyChanged;
- }
-
- var xswitch = (SwitchPresenter)d;
-
- foreach (var xcase in xswitch.SwitchCases)
- {
- // Set our parent
- xcase.Parent = xswitch;
- }
-
- // Will trigger on collection change and case value changed
- xswitch.SwitchCases.Parent = xswitch;
- xswitch.SwitchCases.CaseCollectionChanged += OnCaseValuePropertyChanged;
- }
-
private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// When our Switch's expression changes, re-evaluate.
@@ -110,14 +86,6 @@ private static void OnValuePropertyChanged(DependencyObject d, DependencyPropert
xswitch.EvaluateCases();
}
- private static void OnCaseValuePropertyChanged(object sender, EventArgs e)
- {
- // When something about our collection of cases changes, re-evaluate.
- var collection = (CaseCollection)sender;
-
- collection.Parent.EvaluateCases();
- }
-
///
/// Initializes a new instance of the class.
///
@@ -148,7 +116,7 @@ private void EvaluateCases()
Case xdefault = null;
Case newcase = null;
- foreach (var xcase in SwitchCases)
+ foreach (Case xcase in SwitchCases)
{
if (xcase.IsDefault)
{
@@ -170,19 +138,11 @@ private void EvaluateCases()
newcase = xdefault;
}
- // Only bother changing things around if we have a new case.
+ // Only bother changing things around if we actually have a new case.
if (newcase != CurrentCase)
{
- // Disconnect old content from visual tree.
- if (CurrentCase != null && CurrentCase.Content != null && IsVisualTreeDisconnectedOnChange)
- {
- // TODO: If we disconnect here, we need to recreate later??? Need to Test...
- VisualTreeHelper.DisconnectChildrenRecursive(CurrentCase.Content);
- }
-
- // Hookup new content.
- Content = newcase.Content;
-
+ // If we don't have any cases or default, setting these to null is what we want to be blank again.
+ Content = newcase?.Content;
CurrentCase = newcase;
}
}
@@ -237,6 +197,20 @@ internal static object ConvertValue(Type targetType, object value)
{
return value;
}
+ else if (targetType.IsEnum && value is string str)
+ {
+ if (Enum.TryParse(targetType, str, out object result))
+ {
+ return result;
+ }
+
+ static object ThrowExceptionForKeyNotFound()
+ {
+ throw new InvalidOperationException("The requested enum value was not present in the provided type.");
+ }
+
+ return ThrowExceptionForKeyNotFound();
+ }
else
{
return XamlBindingHelper.ConvertValue(targetType, value);