Click here to Skip to main content
Click here to Skip to main content

dynamic WPF theme by zip

, 31 Mar 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
dynamic WPF theme by zip

Introduction

WPF provide many ways to theme the application, i provide a new way to theme the application dynamically, neither AppDomain, nor loose xaml

Background

Make sure you are familar with the common WPF theme, maybe you can refer to the other great article at first

Using the code

Before present my theme way, let's see what's cons & pros on the classic theme way

Theme strategy

Load Speed

Native support( not require additional code)

Support code themed(bundle code & resource into single file)

Support resource hierarchy navigation

Load dynamically

Unload dynamically

Easily edit and compile(not require VS installed)

Direct Load

Fast

Y

Y

Y

Y

N

N

Loose Xaml

Low

Y

N

Y

Y

Y

Y

AppDomain

Fast

N

Y

N

Y

Y

N

Let's see some fact

  • Xaml support pack protocol Uri
  • pack protocol support custom parser( System.IO.Packaging.PackageStore)
  • WPF support Zip file parser ( System.IO.Packaging.ZipPackage)

Now let's combine these fact into a new theme way

  1. add/remove custom parser for pack protocol
              PackageStore.AddPackage(new Uri("customtheme://"), Package.Open("123.zip"));
              PackageStore.RemovePackage(new Uri("customtheme://")); 
  2. embed resources files/folders to single zip file, i use the 7za.exe (from 7zip command line tools )

    7za.exe

    a

    -tzip

    theme1.customtheme

    .\Themes\theme1\*

    -mm=copy

    Add/ Replace files in zip

    Use zip compress algorithm

    Destination zip file, extension can be changed

    The source files to compressed

    The compress strategy, just copy , don’t do compress to improve the decompress speed

  3. Because ZipPackage is designed for XPS, and XPS require to include a file named [Content_types].xml to identify the content type, so make sure always present a valid [Content_types].xml besides the resource files in the destination zip file
    <?xml version="1.0" encoding="utf-8" ?>
    <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
      <Default Extension="png" ContentType="image/png" />
      <Default Extension="tiff" ContentType="image/tiff" />
      <Default Extension="jpg" ContentType="image/jpeg" />
      <Default Extension="gif" ContentType="image/gif" />
      <Default Extension="bmp" ContentType="image/bmp" />
      <Default Extension="txt" ContentType="text/plain" />
      <Default Extension="xaml" ContentType="application/xaml+xml" />
      <Default Extension="xml" ContentType="application/xml" />
      <Default Extension="avi" ContentType="video/avi" />
      <Default Extension="mp4" ContentType="video/mp4" />
      <Default Extension="mp3" ContentType="audio/mp3" />
    </Types> 
  4. i use MemoryMappedFile to improve IO access speed, because there are many little-size IO access when Xaml load theme files
        Stream fileMapViewStream;
        try
        {
            fileMapViewStream = MemoryMappedFile.OpenExisting(item.Replace("\\", ":"), MemoryMappedFileRights.Read).CreateViewStream(0, new FileInfo(item).Length, MemoryMappedFileAccess.Read);
        }
        catch(IOException)
        {
            fileMapViewStream = MemoryMappedFile.CreateFromFile(item, FileMode.Open, item.Replace("\\", ":"), new FileInfo(item).Length, MemoryMappedFileAccess.Read).CreateViewStream(0, new FileInfo(item).Length, MemoryMappedFileAccess.Read); 
        }
    
  5. At last, we got the most important code for this article
          private void cmbThemes_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                if (e.RemovedItems != null)
                {
                    foreach (var item in e.RemovedItems.OfType<string>())
                    {
                        PackageStore.RemovePackage(new Uri(System.IO.Path.GetFileName(item) + "://"));                                       
                    }
                }
    
    
    
    
                if (e.AddedItems != null)
                {
                    foreach (var item in e.AddedItems.OfType<string>())
                    {
                        Stream fileMapViewStream;
                        try
                        {
                            fileMapViewStream = MemoryMappedFile.OpenExisting(item.Replace("\\", ":"), MemoryMappedFileRights.Read).CreateViewStream(0, new FileInfo(item).Length, MemoryMappedFileAccess.Read);
                        }
                        catch(IOException)
                        {
                            fileMapViewStream = MemoryMappedFile.CreateFromFile(item, FileMode.Open, item.Replace("\\", ":"), new FileInfo(item).Length, MemoryMappedFileAccess.Read).CreateViewStream(0, new FileInfo(item).Length, MemoryMappedFileAccess.Read); 
                        }
                        PackageStore.AddPackage(new Uri(System.IO.Path.GetFileName(item) + "://"), Package.Open(fileMapViewStream, FileMode.Open, FileAccess.Read));
                        Application.Current.Resources.MergedDictionaries[0] = new ResourceDictionary() { Source = new Uri("pack://" + System.IO.Path.GetFileName(item) + ":,,,/ResourceDictionary.xaml") };
                    }
                }
            }
    

At last, let's see the comparison between the three classic theme ways

Theme strategy

Load Speed

Native support( not require additional code)

Support code themed(bundle code & resource into single file)

Support resource hierarchy navigation

Load dynamically

Unload dynamically

Easily edit and compile(not require VS installed)

Direct Load

Fast

Y

Y

Y

Y

N

N

Loose Xaml

Low

Y

N

Y

Y

Y

Y

AppDomain

Fast

N

Y

N

Y

Y

N

Zip file

Fast(*)

N

N

Y

Y

Y

Y

* Though Zip file don't compile the Xaml to baml, but consider the MemoryMappedFile, so will require less IO operation theoretically, speed should be fasterSmile | :)

History

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Yesy
Software Developer (Senior)
China China
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150414.1 | Last Updated 31 Mar 2014
Article Copyright 2014 by Yesy
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid