【发布时间】:2019-07-19 20:51:53
【问题描述】:
我有一个简单的 UIElement,我想把它变成一个 MarkupExtension:
[MarkupExtensionReturnType(typeof(FrameworkElement))]
public class PinkRectangle : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new Rectangle {Height = 100, Width = 300, Fill = Brushes.HotPink };
}
}
它在大多数情况下都非常有效。唯一的例外是在列表中:
<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>
在Collection Syntax 中,它说:
如果属性的类型是集合,则推断的集合类型不需要在标记中指定为对象元素。相反,旨在成为集合中项目的元素被指定为属性元素的一个或多个子元素。每个这样的项目在加载期间被评估为一个对象,并通过调用隐含集合的 Add 方法添加到集合中。
但是,xaml 将上面的语法解释为 MyList = PinkRectangle 而不是 MyList.Add(PinkRectangle) 但是如果我先放入一个 Grid ,它会正确调用 MyList.Add() 。 告诉 xaml 在这两种情况下调用 MyList.Add() 的正确语法是什么?
这是创建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();
}
}
}
- 编辑-
我发现如果我从 MyList 中删除 set{ },问题就消失了,因为 xaml 不再认为有 setter,但最终我需要能够设置 MyList....
【问题讨论】:
-
这有点奇怪。你能详细说明为什么你需要
Window内部的List<object>(特别是有一个公共设置器)以及你为什么要用 UI 元素填充它?从我的角度来看,所有这些似乎都是糟糕的设计。 -
你应该看看 ILSpy 是如何在网格中实现这种类似行为的吗?似乎有一些 IAddChild 接口可以处理这个,可能。
-
@dymanoid - 这只是一个简化的例子。在我的项目中,我有一个基本上由列表框组成的自定义用户控件——用户控件定义了它们的外观和协同工作的方式。我希望能够从实际控制之外设置这些列表中的内容。
标签: c# .net wpf xaml markup-extensions