wpf icon indicating copy to clipboard operation
wpf copied to clipboard

The types `DateOnly` and `TimeOnly` do not get XAML serialized

Open andrei-trandafir-uipath opened this issue 10 months ago • 2 comments

Description

Variables of types DateOnly and TimeOnly do not get serialized when converted to XAML. This is not the case for other date-related standard types like DateTime or DateTimeOffset.

Reproduction Steps

Run the following function in a NET8 environment:

public void TestSerializationForDateTimeOnly()
{
    var dateOnly = new DateOnly(2025, 3, 7);
    var s1 = XamlServices.Save(dateOnly);
    Console.WriteLine(s1);

    var timeOnly = new TimeOnly(21, 49, 3);
    var s2 = XamlServices.Save(timeOnly);
    Console.WriteLine(s2);

    var dateTime = new DateTime(dateOnly, timeOnly, DateTimeKind.Utc);
    var s3 = XamlServices.Save(dateTime);
    Console.WriteLine(s3);
}

Expected behavior

Variables of type DateOnly and TimeOnly should be correctly serialized by XamlServices.Save(...).

Actual behavior

After running the function, notice that:

  • s1 is <?xml version="1.0"?> <DateOnly xmlns="clr-namespace:System;assembly=System.Private.CoreLib"/>
  • s2 is <?xml version="1.0"?> <TimeOnly xmlns="clr-namespace:System;assembly=System.Private.CoreLib"/>
  • However s3 is <?xml version="1.0"?> <DateTime xmlns="clr-namespace:System;assembly=System.Private.CoreLib">2025-03-07T21:49:03Z</DateTime>

Regression?

As far as we know this is not a regression.

Known Workarounds

We have found no workaround so far. We have attempted to follow the steps from https://learn.microsoft.com/en-us/dotnet/desktop/xaml-services/define-custom-types and define custom converters for DateOnly and TimeOnly and then used TypeDescriptor.AddAttribute(...) in order to map the converter to each of the types, but XAML serialization still did not occur. Also, we noticed that the converter DateTimeConverter2 exists in System.Xaml which probably explains why DateTime does get serialized correctly.

Impact

No response

Configuration

OS: Windows 11 on an x64 CPU NET version: 8.0

Other information

No response

andrei-trandafir-uipath avatar Mar 03 '25 15:03 andrei-trandafir-uipath

There is two serializers, System.Xaml.XamlServices.Save and the "original" System.Windows.Markup.XamlWriter.Save.

Normally, the correct way is to supply ValueSerializer (rather than TypeSerializer) as you are not really serializing a type into string, just its value. This works for the original serializer. However, it looks like the System.Xaml.Schema.TypeReflector is not using TypeDescriptor but reflection directly and I would consider this a breaking change from the previous serializer. I would support updating the newer XAML services to use TypeDescriptor.

As a workaround for the new serializer, you can define your own XamlSchemaContext with your XamlType.

Edit: Note that the original serializer does not support DateTimeOffset which is slightly concerning.

miloush avatar Mar 03 '25 18:03 miloush

Indeed, we have noticed as well that the information from TypeDescriptor is ignored by the "new" serializer, System.Xaml.XamlServices.Save(). Having said that, there should be no difference between how the types DateOnly / TimeOnly and the types DateTime / DateTimeOffset are treated by the serializer, given that they are all related. The fact that they are treated differently should be considered a bug. In the mean time, we will investigate the possibility of using a custom XamlSchemaContext as you've suggested.

andrei-trandafir-uipath avatar Apr 24 '25 15:04 andrei-trandafir-uipath