tags:

views:

389

answers:

2

I want to produce some library code that will be included into WPF applications. The library may pop up a Window, depending on circumstances. I can define the Window in XAML, but I'd like to treat the XAML as a template. At runtime, at the time the Window is being created so that it can be displayed, I want to replace certain tags in the Xaml template with runtime-defined values.

What I want to do is something like this:

public partial class DynamicXamlWindow : Window
{
    Button btnUpdate = null;
    public DynamicXamlWindow()
    {
        string s = XamlTemplate;

        // replace some things in the XamlTemplate here

        Window root = System.Windows.Markup.XamlReader.Load(...);
        Object _root = this.InitializeFromXaml(new StringReader(s).ReadToEnd()); //??

        btnUpdate = // ???

        //InitializeComponent();
    }

The XamlTemplate string looks like this:

    private string XamlTemplate = @"
    <Window x:Class='@@CLASS'
            xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
            xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
            Title='@@TITLE' 
            Height='346' Width='380'>

        <Grid>
          ...

I've seen examples where a button or a section is defined in XAML and loaded dynamically. But this is not a button or section. The XamlTemplate provides the XAML for the actual Window.

Is this possible either with InitializeFromXaml or XamlReader.Load ? If so, how?

Can I then retrieve the controls defined in the XAML, for example btnUpdate in the code fragment above. How?

A: 

Yes. When you created a Window in xaml, the auto-generated partial definition includes a method called InitializeComponent. The contents of this method are essentially:

System.Uri resourceLocater = new System.Uri("/SampleWpfApp;component/window1.xaml", System.UriKind.Relative);
System.Windows.Application.LoadComponent(this, resourceLocater);

So what you want, is to call System.Windows.Application.LoadComponent(windowInstance, uri);

siz
+1  A: 

You cannot create a dynamic page that has the x:class attribute. However if the code behind is the same for every dynamic page you can trick it by changing your template to:

private string XamlTemplate = @"
    <control:BaseWindow
            xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
            xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
            xmlns:control='WhateverHere'
            Title='@@TITLE' 
            Height='346' Width='380'>
        <Grid>...

When you are ready to parse this use:

XamlReader.Parse(xaml);

If you wanted to access items in the code behind you would this.FindName("btnUpdate") in the code-behind.

Shaun Bowe