3

I would like to create an WPF Application which retrieves XAML Code from a Database and displays the retrieved code.

Lets say the database return the following code:

<Window x:Class="WpfApplication1.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"> <Grid x:Name="mainGrid"> <Button Content="test case 1" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="100" Click="TestCase1_OnClick" Height="29"/> </Grid> </Window> 

How do i execute this code (or maybe just the content of the mainGrid) during runtime?

3 Answers 3

5

XamlReader class is intened for this purpose. Use its Load method to load the xaml dynamically.

EDIT - This link here might be of your interest.

Sign up to request clarification or add additional context in comments.

6 Comments

As far as i know XamlReader won't work for event handler (Click="TestCase1_OnClick")
Yeah, you can't create handlers with it since it's not loose XAML anymore. Only loose XAML can be loaded with it.
Why do you want to load XAML from the Database. If you explain what you are trying to achieve maybe an alternate implementation can be suggested. For example I would rather have templates built internally , and then get parameters from DB than storing Xaml in the DB.
@Joel - I think you should redesign your code. But however if you want to stick to it, you can use CodeDom to create handlers dynamically. Link here elegantcode.com/2010/12/21/… might be of your interest.
There is no Database, i just created a case to point out the problem. The real problem is much more complicated. But well, lets give it a shot here is what i try to achieve: I receive an user interface defined in an XML File and a corresponding c# code behind file from a webservice. The XML file must be parsed to XAML. Then i have to display the generated XAML file somehow. Basically i have to create a user interface out of an xml file at runtime.
|
3

This is an old question, but I want to suggest a better way without compiling in runtime.

  1. Replacing the "click" attribute with "Command". Implement your Relay command or other third party libraries ( Eg: MVVM Light toolkit ) . Also ICommand MVVM implementation would help.
  2. Remove x:Class attribute from xaml of Window node.

Now you have a loose xaml and task could be done by XamlReader.

Comments

1

This is how i solved the problem:

I have 3 files MainWindow.xaml, MainWindow.xaml.cs and wpftest.csproj.

MainWindow.xaml:

<Window x:Class="wpftest.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"> <Grid> <Button Content="Button" HorizontalAlignment="Left" Margin="122,75,0,0" VerticalAlignment="Top" Width="75" Click="ButtonBase_OnClick"/> </Grid> </Window> 

MainWindow.xaml.cs

namespace wpftest { using System.Windows; /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { MessageBox.Show("Hello world", "does it work?"); } } } 

wpftest.csproj (Note: this file is very large and the most of the stuff is not necessary. You could create a much more simplified solution by following this guide: Walkthrough: Creating an MSBuild Project File from Scratch )

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProjectGuid>{E3FBAE41-AF7E-4C7E-A69E-ADAEAEE76FA2}</ProjectGuid> <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>wpftest</RootNamespace> <AssemblyName>wpftest</AssemblyName> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> <DebugSymbols>true</DebugSymbols> <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\Debug\</OutputPath> <DefineConstants>DEBUG;TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PlatformTarget>AnyCPU</PlatformTarget> <DebugType>pdbonly</DebugType> <Optimize>true</Optimize> <OutputPath>bin\Release\</OutputPath> <DefineConstants>TRACE</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> <Reference Include="System" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> <Reference Include="Microsoft.CSharp" /> <Reference Include="System.Core" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Xaml"> <RequiredTargetFramework>4.0</RequiredTargetFramework> </Reference> <Reference Include="WindowsBase" /> <Reference Include="PresentationCore" /> <Reference Include="PresentationFramework" /> </ItemGroup> <ItemGroup> <Page Include="MainWindow.xaml"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </Page> <Compile Include="MainWindow.xaml.cs"> <DependentUpon>MainWindow.xaml</DependentUpon> <SubType>Code</SubType> </Compile> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project> 

Solution:

The following code snippet will compile the code, created the dll file and use the created dll via reflection. This happens (all) during the application runtime.

Special thanks to doug for this stackoverflow question

 private void TestCase4_OnClick(object sender, RoutedEventArgs e) { var globalProperties = new Dictionary<string, string>(); var buildRequest = new BuildRequestData(@"C:\Users\jbu\wpftest\wpftest.csproj", globalProperties, null, new string[] { "Build" }, null); var pc = new ProjectCollection(); var result = BuildManager.DefaultBuildManager.Build(new BuildParameters(pc), buildRequest); Assembly assembly = Assembly.LoadFrom(@"C:\Users\jbu\wpftest\bin\Debug\wpftest.dll"); var instance = assembly.CreateInstance("wpftest.MainWindow") as Window; if (instance != null) { instance.Show(); } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.