XAMLWriter.Save throwing exception on generics
- Dominant language
- C#
- Stars
- 7.7k
- Forks
- 1.3k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 61
Description
### Description
I have made a WPF dropdown component that is generic, so I can make a Combobox a little less tedious to work with:
```csharp
public class MyDropDown : UserControl
{
private readonly ComboBox _comboBox = new();
public MyDropDown()
{
_comboBox.SelectionChanged += ComboBox_SelectionChanged;
Content = _comboBox;
}
public IEnumerable Items
{
get => (IEnumerable)_comboBox.ItemsSource;
set => _comboBox.ItemsSource = value;
}
public Func DisplayFunc
{
init => _comboBox.ItemTemplate = CreateDataTemplate(value);
}
public Action SelectionChangedAction { get; init; }
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_comboBox.SelectedItem is T selectedItem)
{
SelectionChangedAction(selectedItem);
}
}
private DataTemplate CreateDataTemplate(Func displayFunc)
{
var dataTemplate = new DataTemplate(typeof(T));
var factory = new FrameworkElementFactory(typeof(TextBlock));
factory.SetBinding(TextBlock.TextProperty, new System.Windows.Data.Binding
{
Converter = new FuncValueConverter(displayFunc),
Mode = System.Windows.Data.BindingMode.OneWay
});
dataTemplate.VisualTree = factory;
return dataTemplate;
}
// Converter for converting the Func to a binding-friendly format
private class FuncValueConverter : System.Windows.Data.IValueConverter
{
private readonly Func _func;
public FuncValueConverter(Func func)
{
_func = func;
}
public object? Convert(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture)
{
return value is TInput input ? _func(input) : default;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture)
{
return value is TOutput output ? output : default;
}
}
}
```
### Reproduction Steps
I have a basic test using Xunit with XUnit WpfFact nuget, where I would check for elements in the string:
```csharp
[WpfFact]
public void Test2()
{
var uiElement = new StackPanel
{
Orientation = Orientation.Horizontal,
Children =
{
new MyDropDown()
{
Items = new[] { "One", "Two", "Three" },
DisplayFunc = x => x,
SelectionChangedAction = x => { }
}
}
};
var result = XamlWriter.Save(uiElement);
_outputHelper.WriteLine(result);
Assert.Contains("One", result);
}
```
### Expected behavior
XAMLWriter.Save(...) to return something like:
```xml
// Items
```
### Actual behavior
Throws exception:
```plaintext
System.InvalidOperationException: Cannot serialize a generic type 'Frank.Wpf.Tests.MyDropDown`1[System.String]'.
System.InvalidOperationException
Cannot serialize a generic type 'Frank.Wpf.Tests.MyDropDown`1[System.String]'.
at System.Windows.Markup.Primitives.MarkupWriter.VerifyTypeIsSerializable(Type type)
at System.Windows.Markup.Primitives.MarkupWriter.WriteItem(MarkupObject item, Scope scope)
at System.Windows.Markup.Primitives.MarkupWriter.WriteItem(MarkupObject item, Scope scope)
at System.Windows.Markup.Primitives.MarkupWriter.WriteItem(MarkupObject item)
at System.Windows.Markup.Primitives.MarkupWriter.SaveAsXml(XmlWriter writer, MarkupObject item)
at System.Windows.Markup.XamlWriter.Save(Object obj)
at Frank.Wpf.Tests.XamlSerializerTests.Test2() in D:\frankrepos\Frank.Wpf\Frank.Wpf.Tests\XamlSerializerTests.cs:line 54
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
```
### Regression?
_No response_
### Known Workarounds
Writing one's own "serializer", or rewriting to not use a generic
### Impact
Edge case maybe, but I often include a secret key-combo in my WPF apps that will display a "raw dump" of the XAML and whatever else is loaded in the current window
### Configuration
Windows 11
.net 8
### Other information
Documentation don't state that this is an unreasonable expectation, (accepting generic UiElements): https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/serialization-limitations-of-xamlwriter-save?view=netframeworkdesktop-4.8&viewFallbackFrom=netdesktop-8.0
Contributor guide
Assessment
This issue has not been assessed yet.