Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create DataTemplate from UserControl instance?

Question

Basically I would like to do the following but it seems that I cannot:

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

The question: Is it possible to construct a DataTemplate from UserControl instance? If not, are there any other possible solutions?


Real problem

I'm working on a project where majority of UI views are simple static Word-like documents (e.g some text fields and maybe some images, nothing too fancy). Because most of persons working on this project are not coders we have designed very simple in-house markup language for UI generation. An example of markup of simple view is following:

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

Now these templates are loaded at runtime and usercontrols are created based on them. In this case one usercontrol would be created and it would contain simply couple of stack panels and text blocks so that resulting control would look a bit like text document. XAML equivalent would be something like:

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

Then, I started to implement support for lists but couldn't think of a way how to do that. In theory it is simple and I came up with following syntax (+ XAML equivalent):

[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>

But I can't do that because it seems that I cannot construct DataTemplate directly from UserControl instance. There would be no problems if my UserControls were types, but they are not.

One possible solution is that I could bind ItemsControl.Items directly to list of UserControls (instead of binding to ItemsSource and ItemTemplate) but this is sub-optimal in our case for couple of reasons. I would be willing to try some other solutions first!

Update

For clarification: all I have is plain instance of UserControl class which contains the content I need. 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.

I don't have class for it because I'm constructing it at run-time and I don't want to create new type dynamically by emiting IL code because it is way too painful.

like image 459
user544511 Avatar asked Nov 21 '25 13:11

user544511


1 Answers

Creating a datatemplate from Code behind goes like this:

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

yourItemsControlInstance.ItemTemplate = dt;

A datatemplate is a definition of controls to be built at runtime, that is way this construction with a ElementFactory. You do not want the same instance of the UserControl for every item in your ItemsControl.

like image 103
Grafix Avatar answered Nov 23 '25 03:11

Grafix