如何从UserControl实例创建DataTemplate



问题

基本上我想做以下事情,但似乎我做不到:

UserControl myControl = new UserControl();
DataTemplate template = new DataTemplate(myControl);

问题是:是否可以从UserControl实例构造DataTemplate?如果没有,还有其他可能的解决方案吗?


实际问题

我正在做一个项目,其中大多数UI视图都是简单的静态Word类文档(例如,一些文本字段,也许还有一些图像,没有什么太花哨的)。因为这个项目的大多数工作人员都不是程序员,所以我们为UI生成设计了非常简单的内部标记语言。简单视图的标记示例如下:

First name: [Person.FirstName]
Last name: [Person.LastName]
Address: [Person.Address.Street], [Person.Address.City]

现在,这些模板在运行时加载,并基于它们创建用户控件。在这种情况下,将创建一个用户控件,它将只包含几个堆栈面板和文本块,这样得到的控件看起来有点像文本文档。XAML等价物类似于:

<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="First name: "/>
<TextBlock Text={Binding Person.FirstName}
</StackPanel>
<StackPanel>
...
</StackPanel>
...
</StackPanel>

然后,我开始实现对列表的支持,但想不出如何做到这一点。理论上它很简单,我想出了以下语法(+XAML等效):

[List Customers]
First name: [Person.FirstName]
Last name: [Person.LastName]
Address: [Person.Address.Street], [Person.Address.City]
[EndList]
->
<StackPanel>
<ItemsControl ItemsSource="{Binding Customers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
[Insert code from previous XAML example here]
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>

但我不能这样做,因为我似乎无法直接从UserControl实例构造DataTemplate。如果我的UserControls是类型就不会有问题,但它们不是。

一种可能的解决方案是,我可以将ItemsControl.Items直接绑定到UserControls列表(而不是绑定到ItemsSourceItemTemplate),但在我们的情况下,这是次优的,原因有两个。我愿意先尝试一些其他的解决方案!

更新

为了澄清:我所拥有的只是UserControl类的普通实例,它包含了我需要的内容。例如

UserControl control = new UserControl();
var panel = new StackPanel();
panel.Children.Add(...);
panel.Children.Add(...);
control.Content = panel;
// How to use that control as ItemTemplate for ItemsControl?
// It seems that it is not possible directly but I want to
// know what my options are.

我没有它的类,因为我在运行时构建它,我不想通过发送IL代码来动态创建新类型,因为这太痛苦了。

从代码背后创建数据模板如下:

FrameworkElementFactory factory = new FrameworkElementFactory(MyUserControl.GetType());
DataTemplate dt = new DataTemplate();
dt.VisualTree = factory;
yourItemsControlInstance.ItemTemplate = dt;

数据模板是要在运行时构建的控件的定义,这就是使用ElementFactory构建的方式。您不希望ItemsControl中的每个项都有相同的UserControl实例。

啊,我现在明白你的问题了。我认为没有一种简单的方法(一两行代码)可以从UserControl实例创建数据模板。

但为了解决你的问题,我看到了两个方向:

  1. 在创建用户控件时,创建一个数据模板并使用它。使用嵌套的FrameworkElementFactories会很麻烦。我从来没有这样做过,MSDN文档说,与Xaml中的数据模板相比,您可能会遇到一些无法做到的限制。但如果它很简单,那么它一定是可行的。萨莎·巴伯曾经写过一篇代码项目文章,如果需要的话,你可以作为指导
  2. 将UserControl的创建打包到一个名为private UserControl createMyUserControl(){}的方法中

然后这样做:

ItemsControl itemsControl = new ItemsControl();
foreach (var customer in Customers) 
{
var usercontrol = createMyUserControl(...);
usercontrol.DataContext = customer;
itemsControl.Items.Add(usercontrol);
}

第二个选项在我看来不那么优雅,所以我会先看看选项1。

WPF:如何在代码和神奇的内容中创建样式(参见末尾的一节,了解代码背后的DataTemplate的大量示例)

我认为可以用ContentControl替换UserControl。只需将ContentControl的内容设置为所需的模板,并将其用作ItemsControl的ItemTemplate。

相关内容

  • 没有找到相关文章

最新更新