diff --git a/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconSourceExtension.cs b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconSourceExtension.cs
new file mode 100644
index 00000000000..6e909bd1cb2
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI/Extensions/Markup/FontIconSourceExtension.cs
@@ -0,0 +1,76 @@
+// 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.
+
+using Windows.UI.Text;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Markup;
+using Windows.UI.Xaml.Media;
+
+namespace Microsoft.Toolkit.Uwp.UI.Extensions
+{
+ ///
+ /// Custom which can provide values.
+ ///
+ [Bindable]
+ [MarkupExtensionReturnType(ReturnType = typeof(FontIconSource))]
+ public class FontIconSourceExtension : MarkupExtension
+ {
+ ///
+ /// Gets or sets the representing the icon to display.
+ ///
+ public string Glyph { get; set; }
+
+ ///
+ /// Gets or sets the size of the icon to display.
+ ///
+ public double FontSize { get; set; }
+
+ ///
+ /// Gets or sets the font family to use to display the icon. If , "Segoe MDL2 Assets" will be used.
+ ///
+ public FontFamily FontFamily { get; set; }
+
+ ///
+ /// Gets or sets the thickness of the icon glyph.
+ ///
+ public FontWeight FontWeight { get; set; } = FontWeights.Normal;
+
+ ///
+ /// Gets or sets the font style for the icon glyph.
+ ///
+ public FontStyle FontStyle { get; set; } = FontStyle.Normal;
+
+ ///
+ /// Gets or sets a value indicating whether automatic text enlargement, to reflect the system text size setting, is enabled.
+ ///
+ public bool IsTextScaleFactorEnabled { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the icon is mirrored when the flow direction is right to left.
+ ///
+ public bool MirroredWhenRightToLeft { get; set; }
+
+ ///
+ protected override object ProvideValue()
+ {
+ var fontIcon = new FontIconSource
+ {
+ Glyph = Glyph,
+ FontFamily = FontFamily ?? new FontFamily("Segoe MDL2 Assets"),
+ FontWeight = FontWeight,
+ FontStyle = FontStyle,
+ IsTextScaleFactorEnabled = IsTextScaleFactorEnabled,
+ MirroredWhenRightToLeft = MirroredWhenRightToLeft
+ };
+
+ if (FontSize > 0)
+ {
+ fontIcon.FontSize = FontSize;
+ }
+
+ return fontIcon;
+ }
+ }
+}
diff --git a/UnitTests/Extensions/Test_FontIconSourceExtensionMarkupExtension.cs b/UnitTests/Extensions/Test_FontIconSourceExtensionMarkupExtension.cs
new file mode 100644
index 00000000000..1c1c81852a7
--- /dev/null
+++ b/UnitTests/Extensions/Test_FontIconSourceExtensionMarkupExtension.cs
@@ -0,0 +1,113 @@
+// 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.
+
+using System.Diagnostics.CodeAnalysis;
+using Windows.UI.Text;
+using Microsoft.Toolkit.Uwp.UI.Extensions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Markup;
+
+namespace UnitTests.Extensions
+{
+ [TestClass]
+ public class Test_FontIconSourceExtensionMarkupExtension
+ {
+ [TestCategory("FontIconSourceExtensionMarkupExtension")]
+ [UITestMethod]
+ public void Test_FontIconSourceExtension_MarkupExtension_ProvideSegoeMdl2Asset()
+ {
+ var treeroot = XamlReader.Load(@"
+
+") as FrameworkElement;
+
+ var button = treeroot.FindChildByName("Check") as MockSwipeItem;
+
+ Assert.IsNotNull(button, $"Could not find the {nameof(MockSwipeItem)} control in tree.");
+
+ var icon = button.IconSource as FontIconSource;
+
+ Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button.");
+
+ Assert.AreEqual(icon.Glyph, "\uE105", "Expected icon glyph to be E105.");
+ Assert.AreEqual(icon.FontFamily.Source, "Segoe MDL2 Assets", "Expected font family to be Segoe MDL2 Assets");
+ }
+
+ [TestCategory("FontIconSourceExtensionMarkupExtension")]
+ [UITestMethod]
+ public void Test_FontIconSourceExtension_MarkupExtension_ProvideSegoeUI()
+ {
+ var treeroot = XamlReader.Load(@"
+
+") as FrameworkElement;
+
+ var button = treeroot.FindChildByName("Check") as MockSwipeItem;
+
+ Assert.IsNotNull(button, $"Could not find the {nameof(MockSwipeItem)} control in tree.");
+
+ var icon = button.IconSource as FontIconSource;
+
+ Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button.");
+
+ Assert.AreEqual(icon.Glyph, "\uE14D", "Expected icon glyph to be E14D.");
+ Assert.AreEqual(icon.FontFamily.Source, "Segoe UI", "Expected font family to be Segoe UI");
+ }
+
+ [TestCategory("FontIconSourceExtensionMarkupExtension")]
+ [UITestMethod]
+ public void Test_FontIconSourceExtension_MarkupExtension_ProvideCustomFontIcon()
+ {
+ var treeroot = XamlReader.Load(@"
+
+") as FrameworkElement;
+
+ var button = treeroot.FindChildByName("Check") as MockSwipeItem;
+
+ Assert.IsNotNull(button, $"Could not find the {nameof(MockSwipeItem)} control in tree.");
+
+ var icon = button.IconSource as FontIconSource;
+
+ Assert.IsNotNull(icon, $"Could not find the {nameof(FontIcon)} element in button.");
+
+ Assert.AreEqual(icon.Glyph, "\uE14D", "Expected icon glyph to be E14D.");
+ Assert.AreEqual(icon.FontSize, 7.0, "Expected font size of 7");
+ Assert.AreEqual(icon.FontFamily.Source, "Segoe MDL2 Assets", "Expected font family to be Segoe UI");
+ Assert.AreEqual(icon.FontWeight, FontWeights.Bold, "Expected bold font weight");
+ Assert.AreEqual(icon.FontStyle, FontStyle.Italic, "Expected italic font style");
+ Assert.AreEqual(icon.IsTextScaleFactorEnabled, true, "Expected IsTextScaleFactorEnabled set to true");
+ Assert.AreEqual(icon.MirroredWhenRightToLeft, true, "Expected MirroredWhenRightToLeft set to true");
+ }
+ }
+
+ [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402", Justification = "Mock control for tests")]
+ public class MockSwipeItem : Control
+ {
+ public IconSource IconSource
+ {
+ get => (IconSource)GetValue(IconSourceProperty);
+ set => SetValue(IconSourceProperty, value);
+ }
+
+ public static readonly DependencyProperty IconSourceProperty =
+ DependencyProperty.Register(
+ nameof(IconSource),
+ typeof(IconSource),
+ typeof(MockSwipeItem),
+ new PropertyMetadata(default(IconSource)));
+ }
+}
\ No newline at end of file
diff --git a/UnitTests/UnitTests.csproj b/UnitTests/UnitTests.csproj
index b4208dc4fef..ec379bfb48b 100644
--- a/UnitTests/UnitTests.csproj
+++ b/UnitTests/UnitTests.csproj
@@ -136,6 +136,7 @@
+