I have a simple UIElement that I would like to turn into a MarkupExtension:
[MarkupExtensionReturnType(typeof(FrameworkElement))]
public class PinkRectangle : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new Rectangle {Height = 100, Width = 300, Fill = Brushes.HotPink };
}
}
It works really well in most cases. The only exception is in lists:
<local:WindowEx x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.winfx/200x/xaml"
xmlns:local="clr-namespace:WpfApp1"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
MyProperty="{Binding local:PinkRectangle}"> <!--this one works.-->
<local:WindowsEx.MyList>
<!--<Grid/> If I comment this line in, it works-->
<local:PinkRectangle/>
</local:WindowsEx.MyList>
<ContentPresenter Content="{Binding MyProperty}"/>
</local:WindowEx>
In Collection Syntax, it says:
If the type of a property is a collection, then the inferred collection type does not need to be specified in the markup as an object element. Instead, the elements that are intended to become the items in the collection are specified as one or more child elements of the property element. Each such item is evaluated to an object during loading and added to the collection by calling the Add method of the implied collection.
However, xaml interprets the syntax above as MyList = PinkRectangle
rather than MyList.Add(PinkRectangle)
But if I put in a Grid first, it calls MyList.Add() for both correctly. What is the correct syntax for telling xaml to call MyList.Add() for both situations?
Here's the rest of the code to create a Minimal, Reproducable Example:
namespace WpfApp1
{
// I use this class to directly set a few unusual properties directly in xaml.
public class WindowEx : Window
{
//If I remove the set property, the error goes away, but I need the setter.
public ObservableCollection<object> MyList {get; set; } = new ObservableCollection();
public object MyProperty
{
get { return GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register(nameof(MyProperty), typeof(object), typeof(MainWindow), new PropertyMetaData(0));
}
public partial class MainWindow : WindowEx
{
public MainWindow()
{
InitializeComponent();
}
}
}
- Edit -
I found that if I removed the set{ }
from MyList, the problem went away because xaml no longer thought there was a setter, but ultimately I need to be able to set MyList....
List<object>
inside of aWindow
(especially having a public setter) and why you want to fill it with UI elements? All this seems to be bad design from my point of view. – Erichericha