Practical .NET

Construct XAML Forms at Runtime with Resource Files

WPF makes it very easy to load non-executable resources at run time -- including a complete UI in XAML. Here's how to leverage that functionality to create applications that you can customize without recompiling.

Sometimes different users need different UIs, or different sites where your application is installed need different UIs. You could add a bunch of logic that makes controls visible or invisible as needed (and best of luck testing that). Or you could just load the UI that your user or site needs. In that scenario, the ultimate form contains no content:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

</Window>

At runtime, you'll now need to load the UI based on settings in a config file or the preferences of the currently logged on user. To support that, you can define each of those UIs in your XAML file, then paste each of them into a separate XML file. This example, in a file called MyGrid.xml, defines a Grid containing a DataGrid and two buttons:

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DataGrid Name="DataGrid1" … />
    <Button Name="UpdateBtn" … />
    <Button Content="DeleteBtn" … />
  </Grid>

By default, any XML file you add to your project is a resource file; and when your file absolutely, positively has to be present, a resource file is your best choice. A resource file is compiled into your executable and guaranteed to be distributed with it. If you have a limited number of configurations, you can set them up as individual resource files and compile them all into your executable.

However, if you don't want the file to be incorporated into your executable, you should select the XML file in Solution Explorer and set its Build Action property to Content. A content file won't be distributed with your application (at least if you use any of the standard distribution methods). Instead, it will be a separate file you must copy to the folder holding your executable, but can then replace or modify at your convenience.

To ensure that the file is copied to the folder with your executable (this makes referring to the resource in your code easier), set the file's Copy To Output Directory property. To ensure you get the most recent version of the file, set the file's Copy To Output Directory to Copy If Newer.

Accessing a Resource File
Now you're ready to write the code to load the UI appropriate for your user or installation. First you need to create a StreamResourceInfo class, passing the URI for your resource file. Next, create a XamlReader to pull the XAML from the file.

You can then call the XamlReader's LoadAsync method, passing the Stream property of your StreamResoureInfo object. You'll need to cast the output of the LoadAsync method to the kind of resource you're pulling from the file. For this example, since the file contains a Grid, the output must be cast as a Grid. This code in the form's Window Loaded event does the trick for a resource file:

Dim GridUri As New Uri("/MyGrid.xml", UriKind.Relative)
Dim sri As Windows.Resources.StreamResourceInfo =
         Application.GetResourceStream(GridUri)
Dim xrdr As New System.Windows.Markup.XamlReader()
Dim grd As Grid = CType(xrdr.LoadAsync(sri.Stream), Grid)
Me.Content = grd

The code is only slightly different if you've used a Content file: Instead of using the Application's GetResourceStream method, use its GetContentStream method.

Of course, you'll want to gain access to the controls you've just loaded. Since this code has a variable pointing to the Grid that holds the controls, you can use the Grid's Children collection to access each of the controls the Grid holds. This code accesses the second control (a button) and wires up an event handler for its Click event:

Dim UpdBtn As Button
  UpdBtn = CType(grd.Children(1), Button)
  AddHandler UpdBtn.Click, AddressOf DoUpdate

After deploying your application, you'll be able to modify or replace to update or customize your application -- if you've set your XML files up as a content file. While replacing your whole UI is an extreme example, you could just as easily use this technique with the Content property of a Frame that defines part of your page. Either way, you can eliminate a bunch of control logic that modifies your UI with a half-dozen lines of code that just reads in the right UI.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • .NET 11 Preview 5 Focuses on Performance, Productivity and Safer Code

    .NET 11 Preview 5 focuses on under-the-hood runtime performance gains, streamlined APIs and language features that reduce boilerplate, plus built‑in security checks and incremental ASP.NET Core and EF Core improvements aimed at everyday developer productivity.

  • VS Code 1.124 Focuses on Agent Autonomy and Parallel Sessions

    Microsoft's June 2026 VS Code update turns on Autopilot by default and adds background sending for agent sessions.

  • Developing Agentic Systems in .NET: From Concept to Code

    ZioNet founder Alon Fliess previews his Visual Studio Live! San Diego session on building true agentic systems in .NET -- covering the cognitive loop, MCP tool integration, multi-agent orchestration and enterprise hosting and governance with the Microsoft Agent Framework.

  • Mastering AI Development and Building AI Apps with GitHub Copilot

    Two Microsoft experts explain how GitHub Copilot is evolving from a coding assistant into a broader platform for building, customizing and testing AI-powered developer workflows.

Subscribe on YouTube