Silverpath: My Silverlight development experiences [1] fatal errors when loading xap dynamically

Source: Internet
Author: User
Tags silverlight

Which of the following friends are using the Silverlight program to boot another Silverlight? If you are one of them, you may encounter the following strange problems. If not, you may put down the JS + XAML loader after reading this article... use Silverlight for guidance.

First of all, let's briefly talk about the background. I recently made some of the content of several projects and found that the xap package is very large. It is unfriendly to turn the blue loading circle around. Therefore, we should consider writing a loading program. The interface is beautiful, the progress bar is elegant, and the speed is smooth. Therefore, the load is performed according to the traditional method:

1) Use WebClient to download an xap

2) (optional) obtain the DLL list through the analysis configuration file

3) Load each DLL

4) when loading the mainpage DLL, use reflection to create the mainpage instance.

5) Put it in the current grid/Page

It is not difficult to write it. If you have already written it, skip the next section and go directly to the weird problem section. If you have not written the following code, you can use it as a foreshadowing & getting started ~

---------------------------------- Can be viewed or not-example part of the split line -----------------------------------------

1) create a project

Add a project named largexap. Don't forget to put a video in it .. To increase the video size, set the video to resource resources and compile the video.

We can see two xaps.

One is largexap, our pseudo-Big Data Packet

The other one is what we need to really start. Do not forget to set loadersampletestpage.html as the startup page so that loader can be used for boot. After all the preparations, we can enter the code.

 

 

 

2) XAML Code Section

Double-click mainpage. XAML of loader and add the following code to the layoutroot node.

<TextBlock x:Name="_progress" FontSize="30" Text="0%"/>

In this way, we have created all the required XAML... because it is only for the sake of the following terrorism issues to make a demo, so there is no cool effect of Silverlight. Of course, you can join.

 

To check whether our program is loaded, open the XAML of largexap and add the following code:

<MediaElement Source="Wildlife.wmv" AutoPlay="True"/>
The embedded WMV file can be reflected here, and we can also clearly know whether the largexap program has been started.

3) C # Code Section

Enter mainpage. XAML. CS of loader and modify the code to the following status:

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;namespace LoaderSample{    public partial class MainPage : UserControl    {        public MainPage()        {            InitializeComponent();            this.Loaded += new RoutedEventHandler(MainPage_Loaded);        }        void MainPage_Loaded(object sender, RoutedEventArgs e)        {            WebClient _wc = new WebClient();            _wc.DownloadProgressChanged +=                 new DownloadProgressChangedEventHandler(_wc_DownloadProgressChanged);            _wc.OpenReadCompleted += new OpenReadCompletedEventHandler(_wc_OpenReadCompleted);            _wc.OpenReadAsync(new Uri("LargeXAP.xap", UriKind.Relative));        }        void _wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)        {            _progress.Text = e.ProgressPercentage.ToString() + "%";        }        void _wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)        {            System.Windows.Resources.StreamResourceInfo Info =                 new System.Windows.Resources.StreamResourceInfo(e.Result, "application/binary");            AssemblyPart AP = new AssemblyPart();            System.Reflection.Assembly Asm;            System.Windows.Resources.StreamResourceInfo streamInfo =                 Application.GetResourceStream(Info, new Uri("LargeXAP.dll", UriKind.Relative));            Asm = AP.Load(streamInfo.Stream);            this.Content = (Asm.CreateInstance("LargeXAP.MainPage") as FrameworkElement);        }    }}

Key statement explanation:

System. Windows. Resources. streamresourceinfo info = new system. Windows. Resources. streamresourceinfo (E. result, "application/binary ");

Convert the downloaded xap file to the resource information supported by Silverlight, which is a program file, application/binary

Assemblypart ap = new assemblypart ();

Dynamically create an application component to indicate the existence of a DLL and load it

System. reflection. Assembly ASM;

Prepare the application Assembly object and prepare for subsequent reflection operations

System. Windows. Resources. streamresourceinfo streaminfo = application. getresourcestream (Info, new uri ("largexap. dll", urikind. Relative ));

Create another resource stream to further read the previous resource stream. Read the largexap. dll in xap. 

ASM = ap. Load (streaminfo. Stream );

Read the DLL resource stream to the program component and return an updated current Assembly (ASM ).
This. content = (ASM. createinstance ("largexap. mainpage") as frameworkelement );

Create a mainpage object through reflection and place it on the current page to complete the load Process

 

We have completed this demo and the running results are as follows:

Loading:

Load completed

 

------------------------------------------ Getting started example ---------------------------------------------------

 

Everything looks good, but there are always special cases. Errors sometimes occur unexpectedly. If there is such an application, it uses the app. as a carrier, XAML stores a large amount of resources, that is, apps. resources stores a large number of styles. Using this loader will cause major problems:

Modify app. XAML in largexap to have a resource,

<Application.Resources>    <SolidColorBrush Color="Blue" x:Key="SColorBrush_"/></Application.Resources>

We can see that I have added a resource record. At this time, we modify mainpage. XAML in largexap to display this color.

<Gridx: Name = "layoutroot" background = "{staticresourcescolorbrush _}">

<Mediaelementsource = "wildlife. wmv" autoplay = "true"/>

</GRID>

After binding is added, runLargexap project, [not loader],Check the result and you will find a blue background on the side of the screen. This indicates that our resource has been called.

When the loader is run again, an error will occur:

We can find that vs automatically introduces debug to largexap and tells us that no resource is found.

Based on experience, you may think the same as what I think. The possible solutions should be:

Load app. XAML to the Assembly just now, instead of creating only the mainpage instance.

So I modified the code in loader mainpage. XAML. CS according to this clue and tried to create an app instance. In this way, all resources should be loaded in:

Application _a= (Asm.CreateInstance("LargeXAP.App") as Application);this.Content = (Asm.CreateInstance("LargeXAP.MainPage") as FrameworkElement);

At this time, the program is run.

The error occurs again and the content is the same!

That is to say, the app we created does not play a role. In the end, does it play a role? Set breakpoint debugging.

Take a closer look at the status of _ A and you will find that all resources have been successfully loaded. Why can't I find it?

After carefully thinking about the default start method of the Silverlight program, we found that Silverlight itself does not have a mechanism to allow multiple apps to run at the same time. That is to say, the SL program should be a single-instance application in the ground.

However, here we use an unusual method to forcibly create an app. Does this app have some devastating impact on our current app?

At the same time, it traces the root cause of resource binding. The principle is to submit a query to the parent container, and index the resource that matches the key name. If the parent container does not exist, the app is indexed. In this way, the app becomes a global resource library [logically]. In other words, the premise for an app to become a resource library is to be the parent of all uielements and the highest level of parent. during initialization, we can see that the rootvisual is set, which is the only sub-level of the app. Thus, the only possibility is that the newly created app does not have a relationship with all the uielements in our current operation, resulting in accidental isolation.

You may also think that if you use application. Current to get the current active app, create an app to traverse its resources, and then write it to current, isn't it necessary?

So we modify the code:

Application _a= (Asm.CreateInstance("LargeXAP.App") as Application);foreach (var Res in _a.Resources.Keys){    Application.Current.Resources.Add(Res, _a.Resources[Res]);}this.Content = (Asm.CreateInstance("LargeXAP.MainPage") as FrameworkElement);

However, this seemingly rational code produces the following results:

Duplicate key? Tracking application. Current found that resources in the current app exist, that is, load comes in. But why cannot it affect mainpage ??

When I think about it, I think of an important problem. Silverlight does not have a mechanism for coexistence of multiple apps. When an app is created by reflection, that is, it is not created normally, A default logic will be called, application. current will change to the created app, so that we cannot access the original meaningful app.

So I tried to change the source code segment to the following weird code segment:

Application _real = Application.Current;Application _a= (Asm.CreateInstance("LargeXAP.App") as Application);foreach (var Res in _a.Resources.Keys){    _real.Resources.Add(Res, _a.Resources[Res]);}this.Content = (Asm.CreateInstance("LargeXAP.MainPage") as FrameworkElement);

Taking a closer look, it is actually very simple. Before creating an app, you can take a look at the next object and then operate on the cached app-the original meaningful app.

 

 

The purpose of this article is to avoid detours ~

I'm not talking about it. Let's make a lot of corrections,

 

If there are no special technical errors, I will continue to write this series and share my experiences ~ Thank you for your support!

 

Welcome to online and offline communication ~ Learn from each other ~

 

--------------------------------

Mike Luan

Luancfan@hotmail.com

15801397431

--------------------------------

Provide Silverlight solutions and Silverlight Project Contracting

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.