//
you're reading...
WCF, XAML

Understanding Uncompiled XAML to design dynamic UI in WPF.

Download/Read PDF version here

Introduction: This is a specialized approach that makes sense in certain scenarios where we need highly dynamic user interfaces. We load part of the user interface from a XAML file at runtime using the XamlReader class from the System.Windows.Markup namespace.

One of the most interesting ways to use XAML is to parse it on the fly with the XamlReader.

Let us create a project and load external XAML by using XamlReader in some other XAML window.

Step 1: Add a window application and name is NonCompiledXaml

Step 2: Open Window1.xaml and delete what visual studio adds up and write below code;

<DockPanel xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”&gt;

<Button Name=”button1″ Margin=”30″>Please click me</Button>

</DockPanel>

Here I  have just created a simple button inside dockpanel.

Step 3: At runtime we can load this content in a live window to create the same window. So open window1.xmal.cs and write below code.

public partial class Window1 : Window

{

private Button button1;

public Window1(string xamlFile)

{

InitializeComponent(xamlFile);

}

private void InitializeComponent(string xamlFile)

{

//Configure the form

this.Width = this.Height = 285;

this.Left = this.Top = 100;

this.Title = “Dynamically Loaded XAML”;

//Load the XAML content from external file

DependencyObject rootElement;

using (FileStream fs = new FileStream(xamlFile,FileMode.Open))

{

rootElement = (DependencyObject)XamlReader.Load(fs);

}

//Insert the markup into this window.

this.Content = rootElement;

FrameworkElement frameworkElement = (FrameworkElement)rootElement;

button1 = (Button)frameworkElement.FindName(“button1”);

//Write up the event handler

button1.Click+=new RoutedEventHandler(button1_Click);

}

private void button1_Click(object sender, RoutedEventArgs e)

{

button1.Content = “Thank you.”;

}

}

Here is the explaination of the code:

1. Here, the InitializeComponent() method opens a FileStream on the Window1.xml file.  It then uses the Load() method of the XamlReader to convert the content in this file into a DependencyObject, which is the base from which all WPF controls derive. This Dependency- Object can be placed inside any type of container in this example it’s used as the content for the entire form.

2. To manipulate the button, we need to find the corresponding control object in the dynamically loaded content. The LogicalTreeHelper serves this purpose because it has the ability to search an entire tree of control objects, digging down as many layers as necessary until it finds the object with the name we’ve specified. An event handler is then attached to the Button.Click event.

3. Another alternative is to use the FrameworkElement.FindName() method. In this example, the root element is a DockPanel object. Like all the controls in a WPF window, DockPanel derives from FrameworkElement. That means we can replace this code;

button1 = (Button)LogicalTreeHelper.FindLogicalNode(rootElement, “button1”);

This is equivalent to below code;

FrameworkElement frameworkElement = (FrameworkElement)rootElement;

button1 = (Button)frameworkElement.FindName(“button1”);

Step 4: Let us add a class program.cs to write application statup.

public class Program:Application

{

[STAThread]

static void Main()

{

Program app = new Program();

app.ShutdownMode = ShutdownMode.OnLastWindowClose;

//Our first approach: window with XAML Content

Window1 win = new Window1(“Window1.xaml”);

win.Show();

}

}

Step 5: Run the application and see that now we dynamically loading.

Step 6: Here we saw that we’re loading an element—the DockPanel object—from the XAML file. Alternatively, we could load an entire XAML window In this case, we would cast the object returned by XamlReader.Load() to the Window type and then call its Show() or ShowDialog() method to show it.

So let create a window and load entire XAML window and see how we can cast it.

Add a window and name it as Xaml2009.xaml

Step 7: Write below class inside Xaml2011.xaml. Delete all default XAML added by visual studio.

namespace NonCompiledXaml

{

public class Xaml2009Window : Window

{

public static Xaml2009Window LoadWindowFromXaml(string xamlFile)

{

// Get the XAML content from an external file.

using (FileStream fs = new FileStream(xamlFile, FileMode.Open))

{

Xaml2009Window window = (Xaml2009Window)XamlReader.Load(fs);

return window;

}

}

private void lst_SelectionChanged(object sender, SelectionChangedEventArgs e)

{

MessageBox.Show(e.AddedItems[0].ToString());

}

}

public class Person

{

public string FirstName { get; set; }

public string LastName { get; set; }

public Person(string firstName, string lastName)

{

FirstName = firstName;

LastName = lastName;

}

public override string ToString()

{

return FirstName + ” ” + LastName;

}

}

}

In this case, we would cast the object returned by XamlReader.Load() to the Window type and then call its Show() or ShowDialog() method to show it.

Step 8: Add below XAML in Xaml2009.xaml

<local:Xaml2009Window

xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;

xmlns:local=”clr-namespace:NonCompiledXaml;assembly=NonCompiledXaml”

xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;

xmlns:sys=”clr-namespace:System;assembly=mscorlib”

Width=”300″ Height=”300″ Title=”XAML 2009″>

<StackPanel Margin=”10″>

<Label Target=”{x:Reference txtFirstName}”>_FirstName</Label>

<TextBox x:Name=”txtFirstName” />

<Label Margin=”0,10,0,0″ Target=”{x:Reference txtLastName}”>_LastName</Label>

<TextBox x:Name=”txtLastName” />

<ListBox Margin=”0,25,0,0″ SelectionChanged=”lst_SelectionChanged”>

<x:String>Item One</x:String>

<x:String>Item Two</x:String>

<x:String>Item Three</x:String>

<local:Person>

<x:Arguments>

<x:String>Joe</x:String>

<x:String>McDowell</x:String>

</x:Arguments>

</local:Person>

<sys:Guid x:FactoryMethod=”NewGuid”></sys:Guid>

</ListBox>

</StackPanel>

</local:Xaml2009Window>

Step 9: Update program.cs

public class Program : Application

{

[STAThread()]

static void Main()

{

// Create a program that will show two different windows,

// and will wait until both are closed before ending.

Program app = new Program();

app.ShutdownMode = ShutdownMode.OnLastWindowClose;

// First approach: window with XAML content.

Window1 window1 = new Window1(“Window1.xaml”);

window1.Show();

// Second approach: XAML for complete window.

Xaml2009Window window2 = Xaml2009Window.LoadWindowFromXaml(“Xaml2009.xaml”);

window2.Show();

app.Run();

}

}

Step 10: Run the application

 

When to use this approach : For example, we could create an all-purpose survey application that reads a form file from a web service and then displays the corresponding survey controls (labels, text boxes, check boxes, and so on). The form file would be an ordinary XML document with WPF tags, which we load into an existing form using the XamlReader. To collect the results once the survey is filled out, we simply need to enumerate over all the input controls and grab their content.

Conclusion: Obviously, loading XAML dynamically won’t be as efficient as compiling the XAML to BAML and then loading the BAML at runtime, particularly if our user interface is complex.

However, it opens up a number of possibilities for building dynamic user interfaces.

Thanks for reading

Download/Read PDF version here

www.vishalnayan.wordpress.com

Advertisements

About Vishal

Vishal Nayan is a seasoned professional with hand on Experience on Mircrosoft Technologies. He always look for challenging IT position that allows him to learn new Microsoft Technologies while utilizing experience of Project Development and Software Engineering Ethics. A MCP in WCF ,and looking forward for more.

Discussion

One thought on “Understanding Uncompiled XAML to design dynamic UI in WPF.

  1. I always get a “Could not create unknown type” exception. How can I solve this?

    Posted by Steven | 2012/06/29, 8:26 PM

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

Follow Vishalnayan on WordPress.com

Blog Stats

  • 211,463 hits
%d bloggers like this: