Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - How to programmatically materialize object to visual content?

When you assign an object to a Content control it will materialize a Visual appropriate for that assigned object. Is there a programmatic way to achieve the same result? I would like to call a function in WPF with an object and get back a Visual, where the same logic is applied in generating the Visual as if you had supplied the object to a Content control instance.

For example, if I have a POCO object and assign it to a Content control and there happens to be an appropriate DataTemplate defined then it materializes that template to create the Visual. I would like my code to be able to take a POCO object and get back from WPF the Visual.

Any ideas?

like image 901
Phil Wright Avatar asked Aug 23 '11 01:08

Phil Wright


1 Answers

Use DataTemplate.LoadContent(). Example:

DataTemplate dataTemplate = this.Resources["MyDataTemplate"] as DataTemplate;
FrameworkElement frameworkElement = dataTemplate.LoadContent() as FrameworkElement;
frameworkElement.DataContext = myPOCOInstance;

LayoutRoot.Children.Add(frameworkElement);

http://msdn.microsoft.com/en-us/library/system.windows.frameworktemplate.loadcontent.aspx

If you have a DataTemplate defined for all instances of a type (DataType={x:Type ...}, but no x:Key="...") then you can create content using the appropriate DataTemplate using the following static method. This method also emulates ContentControl by returning a TextBlock if no DataTemplate is found.

/// <summary>
/// Create content for an object based on a DataType scoped DataTemplate
/// </summary>
/// <param name="sourceObject">Object to create the content from</param>
/// <param name="resourceDictionary">ResourceDictionary to search for the DataTemplate</param>
/// <returns>Returns the root element of the content</returns>
public static FrameworkElement CreateFrameworkElementFromObject(object sourceObject, ResourceDictionary resourceDictionary)
{
    // Find a DataTemplate defined for the DataType
    DataTemplate dataTemplate = resourceDictionary[new DataTemplateKey(sourceObject.GetType())] as DataTemplate;
    if (dataTemplate != null)
    {
        // Load the content for the DataTemplate
        FrameworkElement frameworkElement = dataTemplate.LoadContent() as FrameworkElement;

        // Set the DataContext of the loaded content to the supplied object
        frameworkElement.DataContext = sourceObject;

        // Return the content
        return frameworkElement;
    }

    // Return a TextBlock if no DataTemplate is found for the source object data type
    TextBlock textBlock = new TextBlock();
    Binding binding = new Binding(String.Empty);
    binding.Source = sourceObject;
    textBlock.SetBinding(TextBlock.TextProperty, binding);
    return textBlock;
}
like image 145
Harlow Burgess Avatar answered Nov 15 '22 07:11

Harlow Burgess