一.准备XAML文件
有时候我们需要加载一些来自文件,资源中的UI元素,例如保存在XAML文件中的UI元素,在利用MVVM开发时,甚至可能需要动态加载一些视图页面(View)。首先来准备一个待读取的XAML文件,我们可以通过创建一个文本文件并将其扩展名改为.xaml的方式来创建,但更好的方式是在Visual Studio中创建,方法如下:右击解决方案资源管理器中的项目选择添加新项,选择任意一个扩展名为.xaml的项均可,然后将自动生成的内容清空,添加如下的代码:
Rectangle.xaml文件中的XAML代码:
<rectangle xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" VerticalAlignment="Center" HorizontalAlignment="Center" Height="300" Width="350" Fill="#FF0699FF"> </rectangle>
Time.xaml文件中的XAML代码:
<viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <grid Margin="12,0"> </grid><grid Name="backgroundGrid" Visibility="Visible"> <rectangle Name="Rect" Visibility="Visible"></rectangle> </grid> <stackpanel> <textblock Text="{Binding Time.Date}"></textblock> <textblock Text="{Binding Path=Time.TimeOfDay}"></textblock> <button Content="refresh" Command="{Binding RefreshTime}"></button> </stackpanel> </viewbox>
Digital.xaml文件中的XAML代码:
<viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <grid> </grid><grid Name="backgroundGrid" Width="512" Height="512" Visibility="Visible"> <rectangle Fill="#FF0699FF" Name="Rect" Visibility="Visible"></rectangle> </grid> <path Data="M44.2577,25.993998L47.807001,25.993998 47.1796,29.542999 43.629999,29.542999z M25.992382,25.993998L34.714577,25.993998 36.423997,28.114963 35.342048,29.023705C34.822572,29.384381,34.2303,29.55757,33.56743,29.543171L25.776092,29.543171C25.026126,29.543171,24.478051,29.355683,24.130367,28.982107L23.439,28.114963z M4.7394066,25.993998L14.110587,25.993998 15.560999,27.790597 13.482882,29.542999 0.43199921,29.542999z M45.924398,16.558002L49.473999,16.558002 48.846298,20.107 45.296997,20.107z M4.3497849,15.347L5.6699982,16.905554 4.1544895,25.561501 0,28.982001 1.8604641,18.397711C1.9476089,17.921124 2.0452614,17.596934 2.1534042,17.42374 2.2615547,17.250444 2.560854,16.948452 3.0517788,16.514865z M25.53757,14.827L27.009001,16.538094 25.407468,25.582788 22.984321,27.618 22.37731,26.882358C22.045304,26.478637 21.880001,26.081615 21.880001,25.690895 21.880001,25.576287 21.894402,25.426479 21.922999,25.236468L23.46083,16.538094z M39.15077,14.762L40.599998,16.538072 39.236671,24.218849C39.107769,24.998837 39.002268,25.477929 38.922966,25.659025 38.843664,25.838723 38.63776,26.052219 38.306953,26.296916L36.942429,27.335999 35.471,25.539126 37.05183,16.538072z M8.267169,12.987001L15.928335,12.987001 17.422,14.761801 15.971333,15.951967C15.669342,16.19678 15.394648,16.355589 15.149854,16.428593 14.903759,16.500097 14.528769,16.537999 14.024882,16.537999L6.4066133,16.537999 4.9129982,14.804702 6.297246,13.527331C6.5433302,13.296817 6.7879543,13.149709 7.0340395,13.084706 7.2789021,13.019502 7.6902723,12.987 8.267169,12.987001z M27.65837,2.1879997L29.195002,4.1359444 27.63637,12.987253 25.537227,14.827 24.088,12.987253 25.451326,5.3259792C25.566028,4.604681 25.670031,4.1398544 25.765232,3.9301395 25.859034,3.7205563 26.064538,3.4939928 26.380945,3.2479086z M41.747681,2.1449995L42.224291,2.7504482C42.584898,3.2127209 42.766001,3.6449738 42.766001,4.0486479 42.766001,4.1931744 42.742599,4.3806705 42.7008,4.6111355L41.22817,12.98733 39.086227,14.762 37.680001,12.98733 39.237131,4.1359243z M20.4742,2.0580006L21.187798,2.9238424C21.389499,3.1842213 21.490999,3.5384722 21.491,3.9837828 21.490999,4.186903 21.461199,4.4746237 21.403898,4.8509741L20.2359,11.429095C20.162899,11.818395 20.065199,12.121696 19.942899,12.337898 19.820599,12.554096 19.600399,12.806697 19.282801,13.095698L17.9417,14.265 16.491001,12.576197 17.9847,4.1139126z M76.784998,0.67200089L74.600027,13.008158 72.510355,14.903986 73.993364,16.538209 71.959585,28.072174 69.860811,29.846999 68.408998,28.072174 70.443979,16.538209 72.490755,14.900085 71.071642,13.008158 72.609449,4.2007418z M64.664999,0.67200089L62.478701,13.008158 60.390299,14.903986 61.873201,16.538209 59.839502,28.072174 57.7404,29.846999 56.289999,28.072174 58.3239,16.538209 60.370802,14.900085 58.951399,13.008158 60.489202,4.2007418z M57.74095,0.0020008087L64.189997,0.0020008087 59.990896,3.5509996 57.113565,3.5509996 55.577002,1.9496298z M30.926882,0.0020008087L39.020933,0.0020008087C39.684954,0.001999855,40.20447,0.24806213,40.579481,0.73884583L41.228001,1.5824957 38.717422,3.5509996 29.88775,3.5509996 28.220999,1.6267996 29.174129,0.73884583C29.706844,0.24806213,30.291362,0.001999855,30.926882,0.0020008087z M69.860273,0.001999855L76.309999,0.001999855 72.110456,3.5509996 69.232523,3.5509996 67.695997,1.9496298z M17.91575,0.00017929077C18.538841,0.0080728531,19.074799,0.27673435,19.520492,0.80274105L20.039999,1.5174789 17.594667,3.5509996 8.1804581,3.5509996 6.7089996,1.8195648 8.7207451,0.0020771027 17.78997,0.0020771027C17.832283,0.00028514862,17.87421,-0.00034713745,17.91575,0.00017929077z" Stretch="Uniform" Fill="#FFFFFFFF" Width="276" Height="276" Margin="0,0,0,0" RenderTransformOrigin="0.5,0.5"> </path><path .RenderTransform> <transformgroup> </transformgroup><transformgroup .Children> <rotatetransform Angle="0"></rotatetransform> <scaletransform ScaleX="1" ScaleY="1"></scaletransform> </transformgroup> </path> </viewbox>
RSS.xaml文件中的代码:
<listbox xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit" ItemsSource="{Binding RssCollection}" HorizontalAlignment="Stretch"> </listbox><listbox .ItemTemplate> <datatemplate> <stackpanel Margin="10"> <toolkit:expanderview Margin="12,6" Header="{Binding Title}"> <grid> <textblock TextWrapping="Wrap" Text="{Binding Description}"></textblock> </grid> </toolkit:expanderview> <textblock Text="{Binding Time}" Style="{StaticResource PhoneTextSubtleStyle}"></textblock> </stackpanel> </datatemplate> </listbox>
我们需要分别创建这几个文件,添加相应的元素,设置好它们相应的属性即可,注意要添加相应的xml名称空间(xmlns)。在Visual Studio中创建的好处是可以得到设计器的帮助,看到实时的效果,当然也可以使用Expression Blend来做。最后,要注意把Visual Studio自动创建的Code-Behind文件删掉。为了方便起见,我在创建文件时选择的文件类型是text file,添加是将扩展名.txt改成.xaml就可以了。
二.解析XAML文件
要解析XAML文件中的信息,需要借助于XamlReader类,它为分析XAML和创建相应的Silverlight对象树提供XAML处理器引擎。在Silverlight for Windows Phone中它只包含一个静态的Load方法,此方法用来分析一段格式良好的XAML片段并创建相应的Silverlight对象树,然后返回这个对象树的根。Load方法接受一个string类型的参数,我们可以将XAML文件中的代码直接传给它,不过在实际项目中,通常不会硬编码,所以采用与上篇文章中相同的方法,Application类的GetResourceStream方法,代码如下:
T LoadXAMLAndGetShape<t>(string url) { string xaml = string.Empty; StreamResourceInfo sri = Application.GetResourceStream(new Uri(url, UriKind.Relative)); using (StreamReader sr = new StreamReader(sri.Stream)) { xaml = sr.ReadToEnd(); } T shape = (T)XamlReader.Load(xaml); return shape; } </t>
这里我创建了一个泛型方法,以便返回不同类型的对象。在方法中,通过Application.GetResourceStream方法加载XAML文件,然后用StreamReader将它读成字符串,最后将字符串传入XamlReader的Load方法来构造相应的类型。
三.读取并显示对象
首先我添加了一个XamlToObject.cs的文件,代码如下:
using System; using System.Windows; using System.Windows.Resources; using System.Windows.Markup; using System.IO; namespace DynamicLoadXaml { public class XamlToObject { public T LoadXamlFromUrl<t>(string url) { string xaml = string.Empty; StreamResourceInfo sri = Application.GetResourceStream(new Uri(url, UriKind.Relative)); using (StreamReader sr = new StreamReader(sri.Stream)) { xaml = sr.ReadToEnd(); } T shape = (T)XamlReader.Load(xaml); return shape; } public T LoadXamlFromContent</t><t>(string content) { T shape = (T)XamlReader.Load(content); return shape; } } } </t>
在Time.xaml和RSS.xaml中使用到了MVVM模式,就不一一描述了,稍后我会放出源码。接下来是MainPage的相关代码。
MainPage.xaml:
<phone:phoneapplicationpage x:Class="DynamicLoadXaml.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls" xmlns:local="clr-namespace:DynamicLoadXaml" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="800" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="False"> <grid x:Name="LayoutRoot" Background="{StaticResource PhoneBackgroundBrush}"> </grid><grid .DataContext> <local:commonclass></local:commonclass> </grid> <controls:pivot Title="赵榕笔记"> <controls:pivotitem Header="RSS"> <grid Name="grid_rss"> </grid> </controls:pivotitem> <controls:pivotitem Header="Rectangle"> <grid Name="grid_rectangle"> </grid> </controls:pivotitem> <controls:pivotitem Header="Cube"> <grid Name="grid_cube"> </grid> </controls:pivotitem> <controls:pivotitem Header="Digital Gauge"> <grid Name="grid_digital"> </grid> </controls:pivotitem> <controls:pivotitem Header="Time"> <grid Name="grid_time"> </grid> </controls:pivotitem> </controls:pivot> </phone:phoneapplicationpage>
MainPage.xaml.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; namespace DynamicLoadXaml { public partial class MainPage : PhoneApplicationPage { // Constructor public MainPage() { InitializeComponent(); } protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); grid_rectangle.Children.Add(new XamlToObject().LoadXamlFromUrl<rectangle>("/DynamicLoadXaml;component/Files/Rectangle.xaml")); grid_cube.Children.Add(new XamlToObject().LoadXamlFromUrl<viewbox>("/DynamicLoadXaml;component/Files/Cube.xaml")); grid_digital.Children.Add(new XamlToObject().LoadXamlFromUrl</viewbox><viewbox>("/DynamicLoadXaml;component/Files/Digital.xaml")); grid_time.Children.Add(new XamlToObject().LoadXamlFromUrl</viewbox><viewbox>("/DynamicLoadXaml;component/Files/Time.xaml")); grid_rss.Children.Add(new XamlToObject().LoadXamlFromUrl<listbox>("/DynamicLoadXaml;component/Files/RSS.xaml")); } } } </listbox></viewbox></rectangle>
whoah this blog is fantastic i like reading your articles. Keep up the good paintings! You understand, a lot of people are hunting round for this info, you could aid them greatly.
Current blog, fresh information, I read it from time to time!!
I would like this!!!