2013-02-21 79 views
0

我想創建一個WPF應用程序,它從數據庫中檢索XAML代碼並顯示檢索到的代碼。在程序運行時編譯/執行XAML

比方說數據庫返回下面的代碼:

<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> 

我如何在運行時執行該代碼(或者只是在mainGrid的內容)?

回答

1

這是我如何解決了這個問題:

我有3個文件MainWindow.xaml,MainWindow.xaml.cs和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 (注:這個文件是非常大的,最的你可以按照本指南創建一個更簡單的解決方案: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> 

解決方案:

下面的代碼段將編譯代碼,創建的DLL文件,並經由反射使用創建的DLL。這發生在應用程序運行時期間(全部)。

特別感謝dougstackoverflow 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(); 
     } 
    } 
4

XamlReader類是爲此目的而設計的。使用其Load方法動態加載xaml。

編輯 - 此鏈接here可能是你的興趣。

+0

據我所知XamlReader不會爲事件處理程序(點擊=「TestCase1_OnClick」) – Joel 2013-02-21 13:22:55

+2

呀,你不能用它創建處理程序,因爲它的工作而不是「鬆散的XAML」了。只有寬鬆的XAML可以加載它。 – 2013-02-21 13:33:17

+0

爲什麼要從數據庫加載XAML?如果你解釋你正在努力實現的目標,可能會提出一個替代實現。例如,我寧願在內部構建模板,然後從DB獲取參數,而不是在數據庫中存儲Xaml。 – TYY 2013-02-21 13:33:42