Show loading while downloading XAP modules in prism.

4 09 2010

Show loading while downloading XAP modules in prism.

Scenario : To show progress bar when modules (xap’s) in prism are downloaded.

Problem : Currently in prism the default ModuleManager class does not expose a progress event that can be tracked to show some progressing of the modules (xap’s) being downloaded.

Solution : Prism’s ModuleManager internally uses instance of XapModuleTypeLoader to load modules (xap’s) asynchronously. Thanks to the community of prism for providing CreateDownloader() as virtual method.

Straight to the point I will jot down the steps to achieve the above mentioned goal.

Step 1 – Create an event and an event argument classes that will be used in custom class below


public class ModuleDownloadProgressEvent : CompositePresentationEvent<ModuleDownloadProgressArgs>
{
}

public class ModuleDownloadProgressArgs
{
    public ModuleDownloadProgressArgs(int BytesReceived, bool IsComplete) { _BytesReceived = BytesReceived; _IsComplete = IsComplete; }
    private int _BytesReceived;
    public int BytesReceived { get { return _BytesReceived; } set { _BytesReceived = value; } }
    private bool _IsComplete;
    public bool IsComplete { get { return _IsComplete; } set { _IsComplete = value; } }
}

Step 2 – Create a class that derives from IFileDownloader.


public class CustomFileDownloader : IFileDownloader
{
    private readonly WebClient webClient = new WebClient();
    private readonly IEventAggregator eventAgg;

    public CustomFileDownloader()
    {
        eventAgg = ServiceLocator.Current.GetInstance<IEventAggregator>();
    }

    private event EventHandler<DownloadCompletedEventArgs> _downloadCompleted;
    public event EventHandler<DownloadCompletedEventArgs> DownloadCompleted
    {
        add
        {
            if (this._downloadCompleted == null)
            {
                this.webClient.OpenReadCompleted += this.WebClient_OpenReadCompleted;
                this.webClient.DownloadProgressChanged += this.DownloadProgressChanged;
            }

            this._downloadCompleted += value;
        }

        remove
        {
            this._downloadCompleted -= value;
            if (this._downloadCompleted == null)
            {
                this.webClient.OpenReadCompleted -= this.WebClient_OpenReadCompleted;
                this.webClient.DownloadProgressChanged -= this.DownloadProgressChanged;
            }
        }
    }

    void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        RaiseDownloadProgressChanged(e.ProgressPercentage, false);
    }

    private void RaiseDownloadProgressChanged(int val, bool isComplete)
    {
        eventAgg.GetEvent<ModuleDownloadProgressEvent>().Publish(new ModuleDownloadProgressArgs(val, isComplete));
    }

    public void DownloadAsync(Uri uri, object userToken)
    {
        this.webClient.OpenReadAsync(uri, userToken);
    }

    private void WebClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        this._downloadCompleted(this, ConvertArgs(e));
        RaiseDownloadProgressChanged(0, true);
    }

    private static DownloadCompletedEventArgs ConvertArgs(OpenReadCompletedEventArgs args)
    {
        return new DownloadCompletedEventArgs(args.Error == null ? args.Result : null, args.Error, args.Cancelled, args.UserState);
    }
}

Step 3 – Create a class that derives from XapModuleTypeLoader and override its virtual method CreateDownloader returning your class object prepared in step 1


public class CustomXapModuleTypeLoader : XapModuleTypeLoader
{
    protected override IFileDownloader CreateDownloader()
    {
        return new CustomFileDownloader();
    }
}

Step 4 – Create a class that derives from ModuleManager and override its virtual method ModuleTypeLoaders replacing default XapModuleTypeLoader with your class object prepared in step 2.


public class CustomModuleManager : ModuleManager
{
    public CustomModuleManager(IModuleInitializer moduleInitializer, IModuleCatalog moduleCatalog, ILoggerFacade loggerFacade)
        : base(moduleInitializer, moduleCatalog, loggerFacade) { }
    private System.Collections.Generic.IEnumerable<IModuleTypeLoader> typeLoaders;
    public override System.Collections.Generic.IEnumerable<IModuleTypeLoader> ModuleTypeLoaders
    {
        get
        {
            if (this.typeLoaders == null)
            {
                this.typeLoaders = new List<IModuleTypeLoader>()
                                      {
                                          new CustomXapModuleTypeLoader()
                                      };
            }

            return this.typeLoaders;
        }
        set
        {
            this.typeLoaders = value;
        }
    }
}

Step 5 – Register your custom ModuleManager class prepared in step 4, in overridden method ConfigureContainer() of your Bootstrapper class.


	base.RegisterTypeIfMissing(typeof(IModuleManager), typeof(CustomModuleManager), true);

Step 6 – Create a method in Shell that will respond to the ModuleDownloadProgressEvent event when published


public void ShowHide(ModuleDownloadProgressArgs e)
{
	// Your Dream Goes Here
}

Step 7 – Finally in the Shell subscribe to the ModuleDownloadProgressEvent event prepared in Step 1.


	eventAggregator.GetEvent<ModuleDownloadProgressEvent>().Subscribe(ShowHide, ThreadOption.UIThread);

That’s it!!!

Enjoy Prism.

Advertisements

Actions

Information

4 responses

11 06 2012
Harry

Hi
First of I have to thank you for all the amazing information about XAP modules

Secondly is there anyway that you have these information for wordpress users in an easier format

12 06 2012
Dhaval Upadhyaya

Thanks Harry,
Let me know the exact format you want this information.

27 10 2013
wwwsmiama

Thank you so much!!
Can you upload the source code please?

28 10 2013
Dhaval Upadhyaya

Code already depicted in the post.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: