diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue30066.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue30066.cs
new file mode 100644
index 000000000000..985d98daf5d8
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue30066.cs
@@ -0,0 +1,63 @@
+using Microsoft.Maui.Controls;
+using System;
+
+namespace Maui.Controls.Sample.Issues;
+
+[Issue(IssueTracker.Github, "30066", "DatePicker CharacterSpacing Property Not Working on Windows", PlatformAffected.UWP)]
+public class Issue30066 : TestShell
+{
+ protected override void Init()
+ {
+ var shellContent = new ShellContent
+ {
+ Title = "DatePicker CharacterSpacing Test",
+ Content = new Issue30066ContentPage() { Title = "DatePicker CharacterSpacing Test" }
+ };
+
+ Items.Add(shellContent);
+ }
+
+ class Issue30066ContentPage : ContentPage
+ {
+ public Issue30066ContentPage()
+ {
+ var datePicker = new DatePicker
+ {
+ Date = DateTime.Today,
+ CharacterSpacing = 10,
+ AutomationId = "TestDatePicker",
+ HorizontalOptions = LayoutOptions.Center,
+ VerticalOptions = LayoutOptions.Center,
+ };
+
+ var label = new Label
+ {
+ Text = "The DatePicker above should have character spacing of 10 applied to its text.",
+ HorizontalOptions = LayoutOptions.Center,
+ Margin = new Thickness(20),
+ HorizontalTextAlignment = TextAlignment.Center
+ };
+
+ var button = new Button
+ {
+ Text = "Change Character Spacing to 20",
+ AutomationId = "ChangeSpacingButton",
+ HorizontalOptions = LayoutOptions.Center,
+ Margin = new Thickness(0, 20)
+ };
+
+ button.Clicked += (s, e) =>
+ {
+ datePicker.CharacterSpacing = datePicker.CharacterSpacing == 10 ? 20 : 10;
+ button.Text = $"Change Character Spacing to {(datePicker.CharacterSpacing == 10 ? 20 : 10)}";
+ };
+
+ Content = new StackLayout
+ {
+ Children = { datePicker, label, button },
+ Spacing = 20,
+ Margin = new Thickness(20)
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30066.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30066.cs
new file mode 100644
index 000000000000..5ffcf5da66e8
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue30066.cs
@@ -0,0 +1,40 @@
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+
+public class Issue30066 : _IssuesUITest
+{
+ public Issue30066(TestDevice device)
+ : base(device)
+ {
+ }
+
+ public override string Issue => "DatePicker CharacterSpacing Property Not Working on Windows";
+
+ [Test]
+ [Category(UITestCategories.DatePicker)]
+ public void DatePickerCharacterSpacingShouldApply()
+ {
+ App.WaitForElement("TestDatePicker");
+
+ // Take a screenshot to verify character spacing is applied
+ // On Windows, the DatePicker text should show increased character spacing
+ VerifyScreenshot();
+ }
+
+ [Test]
+ [Category(UITestCategories.DatePicker)]
+ public void DatePickerCharacterSpacingCanChange()
+ {
+ App.WaitForElement("TestDatePicker");
+ App.WaitForElement("ChangeSpacingButton");
+
+ // Change the character spacing by clicking the button
+ App.Tap("ChangeSpacingButton");
+
+ // Take a screenshot to verify the character spacing changed
+ VerifyScreenshot();
+ }
+}
\ No newline at end of file
diff --git a/src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs b/src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs
index 9577f4356321..5e65a3f2d9c6 100644
--- a/src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs
+++ b/src/Core/src/Platform/Windows/CharacterSpacingExtensions.cs
@@ -8,5 +8,21 @@ public static int ToEm(this double pt)
{
return Convert.ToInt32(pt * 0.0624f * 1000); // Coefficient for converting Pt to Em. The value is uniform spacing between characters, in units of 1/1000 of an em.
}
+
+ ///
+ /// Converts character spacing from Em units back to the original double value.
+ ///
+ /// The character spacing value in Em units (1/1000 of an em)
+ /// The original character spacing value in points
+ ///
+ /// This method performs the inverse operation of ToEm().
+ /// Em units are defined as 1/1000 of an em, where the conversion coefficient is 0.0624.
+ /// The calculation reverses: originalValue * 0.0624 * 1000 = emValue
+ /// So: originalValue = emValue / (0.0624 * 1000)
+ ///
+ public static double FromEm(this int emValue)
+ {
+ return emValue / (0.0624 * 1000);
+ }
}
}
\ No newline at end of file
diff --git a/src/Core/src/Platform/Windows/DatePickerExtensions.cs b/src/Core/src/Platform/Windows/DatePickerExtensions.cs
index 70a06cf55e15..1179bf562526 100644
--- a/src/Core/src/Platform/Windows/DatePickerExtensions.cs
+++ b/src/Core/src/Platform/Windows/DatePickerExtensions.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using Microsoft.Maui.Graphics;
using Microsoft.UI.Xaml.Controls;
using WBrush = Microsoft.UI.Xaml.Media.Brush;
@@ -38,7 +39,34 @@ public static void UpdateMaximumDate(this CalendarDatePicker platformDatePicker,
public static void UpdateCharacterSpacing(this CalendarDatePicker platformDatePicker, IDatePicker datePicker)
{
- platformDatePicker.CharacterSpacing = datePicker.CharacterSpacing.ToEm();
+ // Store the character spacing value to apply it when ready
+ var characterSpacing = datePicker.CharacterSpacing;
+
+ // Apply immediately if loaded, otherwise wait for load
+ if (platformDatePicker.IsLoaded)
+ {
+ ApplyCharacterSpacingToTextBlocks(platformDatePicker, characterSpacing);
+ }
+ else
+ {
+ // Wait for the control to load, then apply character spacing
+ platformDatePicker.OnLoaded(() => ApplyCharacterSpacingToTextBlocks(platformDatePicker, characterSpacing));
+ }
+ }
+
+ static void ApplyCharacterSpacingToTextBlocks(CalendarDatePicker platformDatePicker, double characterSpacing)
+ {
+ // Find all TextBlock elements within the CalendarDatePicker and apply character spacing
+ var textBlocks = platformDatePicker.GetChildren();
+ var characterSpacingEm = characterSpacing.ToEm();
+
+ foreach (var textBlock in textBlocks)
+ {
+ if (textBlock is not null)
+ {
+ textBlock.CharacterSpacing = characterSpacingEm;
+ }
+ }
}
public static void UpdateFont(this CalendarDatePicker platformDatePicker, IDatePicker datePicker, IFontManager fontManager) =>
diff --git a/src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt
index 7dc5c58110bf..ff62289f322e 100644
--- a/src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt
+++ b/src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt
@@ -1 +1,2 @@
#nullable enable
+static Microsoft.Maui.Platform.CharacterSpacingExtensions.FromEm(this int emValue) -> double
diff --git a/src/Core/tests/DeviceTests/Handlers/DatePicker/DatePickerHandlerTests.Windows.cs b/src/Core/tests/DeviceTests/Handlers/DatePicker/DatePickerHandlerTests.Windows.cs
index c077a59de555..9cbfc2910122 100644
--- a/src/Core/tests/DeviceTests/Handlers/DatePicker/DatePickerHandlerTests.Windows.cs
+++ b/src/Core/tests/DeviceTests/Handlers/DatePicker/DatePickerHandlerTests.Windows.cs
@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.DeviceTests.Stubs;
+using Microsoft.Maui.Platform;
using Microsoft.UI.Xaml.Controls;
using Xunit;
@@ -89,5 +90,53 @@ Color GetNativeTextColor(DatePickerHandler datePickerHandler)
return null;
}
+
+ [Fact]
+ public async Task CharacterSpacingInitializesCorrectly()
+ {
+ var datePicker = new DatePickerStub()
+ {
+ Date = DateTime.Today,
+ CharacterSpacing = 10
+ };
+
+ await ValidatePropertyInitValue(datePicker, () => datePicker.CharacterSpacing, GetNativeCharacterSpacing, 10.0);
+ }
+
+ double GetNativeCharacterSpacing(DatePickerHandler datePickerHandler)
+ {
+ var platformDatePicker = GetNativeDatePicker(datePickerHandler);
+
+ // Since CalendarDatePicker doesn't have CharacterSpacing property directly,
+ // we need to check if it was applied to internal TextBlock elements
+ var textBlocks = platformDatePicker.GetChildren();
+ foreach (var textBlock in textBlocks)
+ {
+ if (textBlock is not null && textBlock.CharacterSpacing > 0)
+ {
+ // Convert back from Em to original value using the extension method
+ return textBlock.CharacterSpacing.FromEm();
+ }
+ }
+
+ return 0.0;
+ }
+
+ [Fact]
+ public async Task CharacterSpacingUpdatesCorrectly()
+ {
+ var datePicker = new DatePickerStub()
+ {
+ Date = DateTime.Today,
+ CharacterSpacing = 5
+ };
+
+ await ValidatePropertyUpdatesValue(
+ datePicker,
+ nameof(IDatePicker.CharacterSpacing),
+ GetNativeCharacterSpacing,
+ 5.0,
+ 15.0);
+ }
}
}