动态加载带有代码的XAML文件 [英] Dynamically load a XAML file with code behind

查看:107
本文介绍了动态加载带有代码的XAML文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好。我想在运行时加载外部XAML文件(包括后面的代码)。我能够加载XAML文件的内容:

 尝试 
{
FileStream Fs = new FileStream( @ C: / XAML Files / ucMain.xaml,FileMode.Open);
Page grdToLoad = new Page();
grdToLoad.Height = 210 ;
grdToLoad.Width = 400 ;
grdToLoad = System.Windows.Markup.XamlReader.Load(Fs) as Page;
gridMain.Children.Add(grdToLoad);
Fs.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}



这很完美,但我似乎无法加载代码。我尝试过使用x:Code,但我一直收到错误:

无法从文本'Clicked'创建'点击'。'行号'4'和行位置'26 '。



XAML文件:

 < ;  网格  

xmlns < span class =code-keyword> = http://schemas.microsoft.com/winfx/2006/xaml/presentation

xmlns:x = http://schemas.microsoft.com/winfx/2006/xaml >
< 按钮 名称 = 但主要 点击 = 点击 > 点击我!< /按钮 >
< x:代码 > < span class =code-keyword><![CDATA [
void Clicked(对象发送者,RoutedEventArgs) e)
{
MessageBox.Show(Hello World!);
}
< / x:代码>
< / Grid>





如果我删除x:代码和点击事件,一切似乎都很好。是否可以在运行时加载.cs文件而不是使用x:Code?如果没有,我怎么能修复这个错误?



提前谢谢。

解决方案

为什么不尝试创建包含xaml的UserControl。这样,您可以获得所有代码的好处,并可以在您的调用方法中实例化代码:



  .gridMain.Children.Add( new  MyUserControl()); 





这样,您可以保持适当的分隔,并可以在用户控件或父窗口/控件中挂钩按钮单击事件。


< blockquote>

 <  网格  

xmlns = http:// schemas.microsoft.com/winfx/2006/xaml/presentation\"

xmlns:x = http://schemas.microsoft.com/winfx/2006/xaml >
< 按钮 名称 = 但主要 点击 = 点击 > 点击我!< /按钮 >
< x:代码 > <![CDATA [
void Clicked(对象发件人,RoutedEventArgs) e)
{
MessageBox.Show(Hello World!);
}
]]>
<! - 忘记结束标记 - >
< / x:代码 >
< / Grid >



您忘记了CDATA部分的结束标记。我猜测你的例子中你使用的是原始网站文件,但我强烈建议你重新思考,如果这是你的 XAML文件,而不是内在的外部文件。您可以将Build Action设置为Page,它将XAML编译为嵌入在程序集中的BAML文件。它不仅减少了您的版本中的单个文件的数量,而且还允许轻松加载:

页面页面= Application.LoadComponent( new  Uri(  / Page1.xaml,UriKind.Relative))  as  Page; 
if (page!= null
gridMain.Children.Add(page );



这样可以正常工作但是你会收到警告, Page 并不打算成为除了 Window Frame 之外的任何其他子项。只需将加载的 Page 包装在 Frame 中,然后将其作为子项添加到<$中即可轻松解决c $ c>网格。

示例:

 Uri uri =  new  Uri(  / Page1.xaml,UriKind.Relative); 
Page page = Application.LoadComponent(uri) as Page;
Frame frame = new Frame();
frame.Content = page;
// 或frame.Source = uri;这让WPF可以控制你的负载。
gridMain.Children.Add(frame);





我的完整的工作代码:

 <! -    < span class =code-comment> MainWindow.xaml    - >   
< 窗口 x:Class = Testing_xClass_and_xCode.MainWindow

xmlns = http://schemas.microsoft.com/winfx/2006/ xaml / presentation

xmlns:x = http ://schemas.microsoft.com/winfx/2006/xaml

< span class =code-attribute> xmlns:d = http://schemas.microsoft.com/expression/blend/2008

xmlns: mc = http://schemas.openxmlformats.org/markup-compatibility/2006

xmlns:local = clr-namespace:Testing_xClass_and_xCode

mc:可忽略 = < span class =code-keyword> d

标题 = MainWindow 高度 = 350 宽度 = 525 >
< 网格 < span class =code-attribute> 名称 = gridMain / >
< / Window >
<! - < span class =code-comment> Page1.xaml - >
< Page x:Class = Testing_xClass_and_xCode.Page1

xmlns = http://schemas.microsoft.com/winfx/2006/xaml/presentation

xmlns:x = http://schemas.microsoft.com/winfx/ 2006 / xaml

xmlns:mc = http://schemas.openxmlformats.org/markup-compatibilit y / 2006

xmlns:d = http://schemas.microsoft.com/expression/blend/2008

xmlns :local = clr-namespace:Testing_xCla ss_and_xCode

mc:Ignorable = d

d:DesignHeight = 300 d:DesignWidth < span class =code-keyword> = 300
< span class =code-attribute>
标题 = Page1 >
< 网格 < span class =code-attribute>

< span class =code-attribute> xmlns = http:// schemas。 microsoft.com/winfx/2006/xaml/presentation\"

xmlns:x = http://schemas.microsoft.com/winfx/2006/xaml >
< 按钮 名称 = < span class =code-keyword> butMain 点击 = 点击 > 点击我!< /按钮 >
< x:代码 >
<![CDATA [
void Clicked(object sender, RoutedEventArgs e)
{
MessageBox.Show(Hello World!);
}
]]>

< / x:代码 >
< ; / Grid >
< / Page >





  //   MainWindow.xaml。 cs  
命名空间 Testing_xClass_and_xCode
{
public < span class =code-keyword> partial class MainWindow:Window
{
public MainWindow()
{
InitializeComponent();
尝试
{
页页= Application.LoadComponent( new Uri( / Page1.xaml,UriKind.Relative)) as 页面;
if (page!= null
gridMain.Children.Add(page );
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}





编辑:简短说明:As John Simmons指出,您应该考虑将其设为 UserControl 页面旨在可导航。您所做的只是封装控件,这就是 UserControl 存在的原因。话虽这么说,WPF非常灵活,可以让你做任何事情。


Hi. I would like to load an external XAML file (including the code behind) during runtime. I was able to load the content of the XAML file:

try
{
    FileStream Fs = new FileStream(@"C:/XAML Files/ucMain.xaml", FileMode.Open);
    Page grdToLoad = new Page();
    grdToLoad.Height = 210;
    grdToLoad.Width = 400;
    grdToLoad = System.Windows.Markup.XamlReader.Load(Fs) as Page;
    gridMain.Children.Add(grdToLoad);
    Fs.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}


This works perfect, but I can't seem to load the code behind. I have tried using x:Code, but I keep on getting an error:
"Failed to create a 'Click' from the text 'Clicked'.' Line number '4' and line position '26'."

The XAML file:

<Grid

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
  <Button Name="butMain" Click="Clicked">Click Me!</Button>
  <x:Code><![CDATA[
    void Clicked(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Hello World!");
    }
  </x:Code>
</Grid>



If I remove the x:Code and the Click event, everything seems to work fine. Would it be possible to load the .cs file during runtime instead of using x:Code? If not, how would I be able to fix this error?

Thanks in advance.

解决方案

Why don't you try creating a UserControl that contains your xaml. That way, you get all the benefits of having the code behind and can instantiate the code in your calling method:

this.gridMain.Children.Add(new MyUserControl());



That way, you maintain proper compartmentalization, and can hook the button click event either in your user control, or in the parent window/control.


<Grid

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
  <Button Name="butMain" Click="Clicked">Click Me!</Button>
  <x:Code><![CDATA[
    void Clicked(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Hello World!");
    }
  ]]> <!-- Forgot the closing tag -->
  </x:Code>
</Grid>


You forgot the closing tag for the CDATA section. I'm guessing from your example you're using a site-of-origin file but I'd highly recommend re-thinking that if this is your XAML file and not something intrinsically external. You can set the Build Action to "Page" which will compile the XAML into a BAML file embedded in the assembly. Not only does it reduce the number of individual files in your release but also allows easy loading with:

Page page = Application.LoadComponent(new Uri("/Page1.xaml", UriKind.Relative)) as Page;
if (page != null)
  gridMain.Children.Add(page);


This will work just fine but you will be warned that a Page isn't intended to be the child of anything other than a Window or Frame. That could be easily remedied by just wrapping the loaded Page in a Frame and adding that as a child to the Grid.
Example:

Uri uri = new Uri("/Page1.xaml", UriKind.Relative);
Page page = Application.LoadComponent(uri) as Page;
Frame frame = new Frame();
frame.Content = page;
//Or frame.Source = uri; This lets WPF control the loading for you.
gridMain.Children.Add(frame);



My full working code:

<!-- MainWindow.xaml -->
<Window x:Class="Testing_xClass_and_xCode.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:Testing_xClass_and_xCode"

        mc:Ignorable="d"

        Title="MainWindow" Height="350" Width="525">
    <Grid Name="gridMain" />
</Window>
<!-- Page1.xaml -->
<Page x:Class="Testing_xClass_and_xCode.Page1"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

      xmlns:local="clr-namespace:Testing_xClass_and_xCode"

      mc:Ignorable="d" 

      d:DesignHeight="300" d:DesignWidth="300"

      Title="Page1">
    <Grid

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
        <Button Name="butMain" Click="Clicked">Click Me!</Button>
        <x:Code>
            <![CDATA[
            void Clicked(object sender, RoutedEventArgs e)
            {
                MessageBox.Show("Hello World!");
            }]]>
        </x:Code>
    </Grid>
</Page>



//MainWindow.xaml.cs
namespace Testing_xClass_and_xCode
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            try
            {
                Page page = Application.LoadComponent(new Uri("/Page1.xaml", UriKind.Relative)) as Page;
                if (page != null)
                    gridMain.Children.Add(page);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
    }
}



EDIT: A short note: As John Simmons pointed out, you should consider making this a UserControl instead. A Page is designed to be navigable. All you're doing is encapsulating controls which is why UserControl exists. That being said, WPF is very flexible and will let you do most anything.


这篇关于动态加载带有代码的XAML文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆