如何从UserControl实例创建DataTemplate?

时间:2012-11-29 12:04:09

标签: c# wpf user-controls 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列表(而不是绑定到 ItemsSource ItemTemplate )但是由于几个原因,这在我们的案例中是次优的。我愿意先尝试其他一些解决方案!

更新

为了澄清:我所拥有的只是UserControl类的普通实例,其中包含我需要的内容。 E.g。

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代码来动态创建新类型,因为它太痛苦了。

3 个答案:

答案 0 :(得分:3)

从Code后面创建一个datatemplate就像这样:

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

yourItemsControlInstance.ItemTemplate = dt;

datatemplate是要在运行时构建的控件的定义,这是使用ElementFactory进行构造的方式。对于ItemsControl中的每个项目,您不需要UserControl的相同实例。

答案 1 :(得分:1)

我现在明白你的问题了。我不认为从UserControl实例创建数据窗口有一种简单的方法(一行或两行代码)。

但要解决您的问题,我会看到两个方向:

  1. 在创建usercontrol的位置,创建一个datatemplate并使用它。使用嵌套的FrameworkElementFactories会很麻烦。我从来没有这样做过,MSDN文档说你可能会遇到一些与Xaml中的datatemplates相比无法做到的限制。但如果它很简单,那一定是可行的。曾经有过Sacha Barber的代码项目文章,您可以将其用作指导(如果需要)。
  2. 您在名为private UserControl createMyUserControl(){}
  3. 的方法中打包UserControl的创建

    做这样的事情:

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

    我认为第二种选择不太优雅,所以我先看看选项1。

    WPF: How to create Styles in code/and magical Content (see section at the end for extensive sample of a DataTemplate in Code behind)

答案 2 :(得分:0)

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