【问题标题】:Loading XAML XML through runtime?通过运行时加载 XAML XML?
【发布时间】:2010-11-02 11:49:50
【问题描述】:

我们正在将 Winforms 迁移到基于 WPF 的解决方案。我们有自定义 XML 定义,用于在运行时构建 Windows 窗体。

由于 XAML 是基于 XML 的,我们是否可以使用 XAML 定义定义一个 HelloWorldWindow.xml 文件,并且是否可以将其加载到 WPF 应用程序中而无需任何 CSharp 文件后面的代码?我们将在运行时附加钩子后面的代码。

如何在运行时附加后面的代码?

【问题讨论】:

  • 你说的这个xml文件真的是一个有效的XAML文件吗?
  • @Steve,是的,它是有效的 xaml 文件。但我们希望在运行时附加代码实现。
  • 得到了一个应用大多数 MVVM 概念的可行解决方案:[我的解决方案][1] [1]:stackoverflow.com/questions/9021677/…

标签: c# .net wpf xaml


【解决方案1】:

使用此 XAML 创建 XML 文件 Tempwin.xml

<UserControl 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300" Background="Transparent" >
<Border Background="Black" CornerRadius="10" BorderThickness="4" BorderBrush="RoyalBlue">
<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="Sample Text" Foreground="White" Margin="2"></TextBlock>
        <TextBox Grid.Row="1" Margin="5"> </TextBox>
        <TextBlock Text="Sample Text 1" Grid.Row="2" Foreground="White" Margin="2"></TextBlock>
        <TextBox Grid.Row="3" Margin="5"></TextBox>
        <Ellipse Fill="Red" Height="100" Width="100" Grid.Row="4" Margin="0,10,0,0"></Ellipse>
    </Grid>
    </Border>

使用以下 xaml 创建示例 WPF 应用程序

<Window x:Class="WpfApplication12.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>

    </Grid.RowDefinitions>

    <Button Height="25" Width="100" Margin="2" Click="Button_Click"> Show Content</Button>
    <Grid x:Name="content" Grid.Row="1" Margin="2">

    </Grid>
</Grid>

将以下 C# 代码粘贴到 Button_Click 后面的代码中

  StreamReader mysr = new StreamReader(@"D:\Tempwin.xml");
        FrameworkElement  rootObject = XamlReader.Load(mysr.BaseStream) as FrameworkElement;
        content.Children.Add(rootObject);

如果你想在运行时加载 xaml,你不能在你的 XAML 文件后面提供任何代码。所以我在创建 xml 之前删除了 x:Class 属性

事件挂钩....

<UserControl 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300" Background="Transparent" >
<Border Background="Black" CornerRadius="10" BorderThickness="4" BorderBrush="RoyalBlue">
<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="Sample Text" Foreground="White" Margin="2"></TextBlock>
        <TextBox Grid.Row="1" Margin="5"> </TextBox>
        <TextBlock Text="Sample Text 1" Grid.Row="2" Foreground="White" Margin="2"></TextBlock>
        <TextBox Grid.Row="3" Margin="5"></TextBox>
        <Ellipse Fill="Red" Height="100" Width="100" Grid.Row="4" Margin="0,10,0,0"></Ellipse>
        <Button Grid.Row="5" Height="25" Content="Event added at Runtime" x:Name="btnTest"></Button>
    </Grid>
    </Border>

Button ButtoninXAML;

    private void Button_Click(object sender, RoutedEventArgs e)
    {

        StreamReader mysr = new StreamReader(@"D:\Tempwin.xml");
        FrameworkElement  rootObject = XamlReader.Load(mysr.BaseStream) as FrameworkElement;
        ButtoninXAML = LogicalTreeHelper.FindLogicalNode(rootObject, "btnTest") as Button;
        ButtoninXAML.Click += new RoutedEventHandler(Button_Click1); 

        content.Children.Add(rootObject);

    }
    private void Button_Click1(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Added At Runtime");
    }

【讨论】:

    【解决方案2】:

    您可以像这样动态显示 Xaml:

        string text = @"<TextBlock Text='test' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' />";
    
        // Convert to stream
        // You can also just stream the xaml from a file, using a FileStream
        MemoryStream stream = new MemoryStream(ASCIIEncoding.UTF8.GetBytes(text));
    
        // Convert to object
        TextBlock block = (TextBlock)System.Windows.Markup.XamlReader.Load(stream);
    
        //... now you can put that TextBlock somewhere, for example in your main Window
    

    有关详细信息,请参阅 XamlReader 类: http://msdn.microsoft.com/en-us/library/ms613427%28v=VS.95%29.aspx

    【讨论】:

    • 可以直接使用XamlReader.Parse解析字符串,无需创建MemoryStream。
    【解决方案3】:

    我已经在运行时加载了 XAML,这是一个简短的示例

    Grid grd = new Grid();
    var grdEncoding = new ASCIIEncoding();
    var grdBytes = grdEncoding.GetBytes(myXAML);
    grd = (Grid)XamlReader.Load(new MemoryStream(grdBytes));
    Grid.SetColumn(grd, 0);
    Grid.SetRow(grd, 0);
    parentGrid.Children.Add(grd);
    
    private String myXAML = @" <Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Margin='30 10 30 65' VerticalAlignment='Bottom'>" +
                    "<Label Content='Date: 1-Feb-2013' FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Left'/>" +
                    "<Label Content='4'  FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Center'/>" +
                    "<Label Content='Hello World'  FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Right'/>" +
                "</Grid>";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多