范例来自webcast,由于版本问题,对其中代码做出了修正。简单示范在silverlight中如何动态加载xap文件。

     动态加载,也就是要在运行时,加载并解析包含xap文件信息的AppManifest.xaml文件,找到合适的dll信息,通过反射机制生成silverlight相关实例。
     
     建立项目,包括三个专案:其中DynamicXap为要动态加载的xap,TanMiLiLie为一个web应用。

Silverlight2.0动态加载xap文件

此项目DynamicXap最终的标注文件AppManifest.xaml。


  <Deployment.Parts>
    
<AssemblyPart x:Name="DynamicXap" Source="DynamicXap.dll" />
    
<AssemblyPart x:Name="System.Windows.Controls.Data" Source="System.Windows.Controls.Data.dll" />
    
<AssemblyPart Source="zh-Hans/System.Windows.Controls.Data.resources.dll" />
  
</Deployment.Parts>
</Deployment>

     在AssemblyPart name="DynamicXap" 的source中包含的DynamicXap.dll即是此xap文件包含的有效dll,其中包含了若干page文件,我们就是要通过解析此标注文件来生成特定的page信息。

 DynamicXap中现在只包括个Page.xaml,其中的定义:


    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" 
   
>
    
<Grid x:Name="LayoutRoot" Background="White">
    
<data:DataGrid x:Name="dgshow" AutoGenerateColumns="True" ItemsSource="{Binding}"></data:DataGrid>
    
</Grid>
</UserControl>

TanMiLiLie:在此silverlight应用动态加载上述xap文件。


    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width
="800" Height="700">
    
<Canvas  Background="Khaki">
        
<TextBlock Canvas.Left="50" Canvas.Top="100" Text="InPut:" Foreground="Red" FontSize="20"></TextBlock>
        
<TextBox x:Name="txtInput" Canvas.Left="120" Canvas.Top="100" Width="150" ></TextBox>
        
<Button x:Name="btn" Canvas.Left="150" Canvas.Top="140" Height="30" Width="80" Content="Confirm" Click="btn_Click"></Button>
        
<TextBlock x:Name="txtshow" Canvas.Left="150" Canvas.Top="200" Text=""></TextBlock>
        
<Canvas x:Name="divshow" Canvas.Top="220" Canvas.Left="50" Height="200" Width="600" Background="White"></Canvas>
    
</Canvas>
</UserControl>
CodeBind:
 TanMiXiLie
{
    public partial class Page : UserControl
    {
        
public Page()
        {
            InitializeComponent();
        }

        
private void btn_Click(object sender, RoutedEventArgs e)
        {
            WebClient client 
= new WebClient();
            client.OpenReadCompleted 
+= new OpenReadCompletedEventHandler(client_OpenReadCompleted);

            
//打开打包的xap文件
            client.OpenReadAsync(new Uri("DynamicXap.xap", UriKind.Relative));
        }

        
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            
//解包,读取AppManifest.xaml文件信息
            string appManifest = new StreamReader(Application.GetResourceStream(new StreamResourceInfo(e.Result, null), new Uri("AppManifest.xaml", UriKind.Relative)).Stream).ReadToEnd();

            
//------------解析AppManifest.xaml信息内容

            XElement deploymentRoot 
= XDocument.Parse(appManifest).Root;
            List
<XElement> deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
                                              select assemblyParts).ToList();

            Assembly asm 
= null;
            
foreach (XElement xElement in deploymentParts)
            {
                
string source = xElement.Attribute("Source").Value;
                AssemblyPart asmPart 
= new AssemblyPart();
                StreamResourceInfo streamInfo 
= Application.GetResourceStream(new StreamResourceInfo(e.Result, "application/binary"), new Uri(source, UriKind.Relative));
                
if (source == "DynamicXap.dll")
                {
                    asm 
= asmPart.Load(streamInfo.Stream);
                }
                
else
                {
                    asmPart.Load(streamInfo.Stream);
                }
            }

            
//======================

            divshow.Children.Clear();

            divshow.DataContext 
= DataOP.getUsers(txtInput.Text);

            
//转换此assembly为UIElement
            UIElement myData = asm.CreateInstance("DynamicXap.Page"as UIElement;

            divshow.Children.Add(myData);

            divshow.UpdateLayout();
        }
    }
}
其中涉及到的两个class的定义:
 UserInfo
    {
        public string ID
        {
            
set;
            
get;
        }
        
public string Name
        {
            
set;
            
get;
        }
        
public string Address
        {
            
set;
            
get;
        }
        
public string Tel
        {
            
set;
            
get;

        }
    }

 

 DataOP
    {
        public static List<UserInfo> getUsers(string str)
        {
            List
<UserInfo> lists=getAllUsers();

            var list 
= from p in lists
                       
where p.Name.ToLower().StartsWith(str)
                       select p;

            
return list.ToList();
        }

        
private static List<UserInfo> getAllUsers()
        {
            List
<UserInfo> lists = new List<UserInfo>() 
            {
               
new UserInfo(){ ID="1001", Name="Ivan", Address="SZ", Tel="123456"},
               
new UserInfo(){ ID="1002", Name="Evan", Address="SZ", Tel="123456"},
               
new UserInfo(){ ID="1004", Name="Bvan", Address="SZ", Tel="123456"},
               
new UserInfo(){ ID="1003", Name="Cvan", Address="SZ", Tel="123456"},
               
new UserInfo(){ ID="1005", Name="Ivan", Address="SZ", Tel="123456"},
               
new UserInfo(){ ID="1006", Name="Fvan", Address="SZ", Tel="123456"},
               
new UserInfo(){ ID="1007", Name="Ivan", Address="SZ", Tel="123456"},
            };

            
return lists;
        }
    }

最后运行web应用TanMiXiLieTestPage.aspx,即可看到最终效果。

注:1.其中涉及Linq to xml ,Linq to Collection的应用
      2.WebClient的应用。
      3.解析AppManifest.xaml时,采用linq to xml方式,避免了“Invalidoperation” 异常的出现。

相关文章: