WPF 动态加载主题由zip
经典主题的方式
主题战略 |
加载速度 |
本机支持 (不需要额外的代码) |
支持代码为主题 (捆绑代码 & 资源成单独的文件) |
支持资源层次结构中导航 |
动态加载 |
动态卸载 |
轻松地编辑和编译 (不需要安装 VS) |
直接负载 |
快速 |
Y |
Y |
Y |
Y |
N |
N |
松散 Xaml |
低 |
Y |
N |
Y |
Y |
Y |
Y |
AppDomain |
快速 |
N |
Y |
N |
Y |
Y |
N |
项目资源目录截图:
2.添加/删除自定义分析器包协议
1 PackageStore.AddPackage(new Uri("customtheme://"), Package.Open("123.zip")); 2 PackageStore.RemovePackage(new Uri("customtheme://"));
3.7za命令行压缩方式
7za.exe |
a |
-tzip |
theme1.customtheme |
.\Themes\theme1\* |
-m m = 复制 |
添加/替换 zip 中的文件 |
使用 zip 压缩算法 |
目的地 zip 文件中,可以更改扩展名 |
要压缩的源文件 |
压缩策略,只复制,不做压缩以提高 decompress 速度 |
>cd C:\Users\rhg\Desktop\ThemeInZip\7za920
>7za.exe a -tzip theme1.customtheme C:\Users\rhg\Desktop\ThemeInZip\Themes\theme1\* -m m = 复制
4.我使用MemoryMappedFile来提高 IO 访问速度,因为有很多小大小 IO 访问当 Xaml 加载的主题文件。
1 public MainWindow() 2 { 3 InitializeComponent(); 4 //PackageStore.AddPackage(new Uri("customtheme://"), Package.Open("123.zip")); 5 cmbThemes.ItemsSource = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory + "\\Themes").EnumerateFileSystemInfos("*.customtheme", SearchOption.TopDirectoryOnly).Select((fi) => fi.FullName).ToList(); 6 7 } 8 9 private void cmbThemes_SelectionChanged(object sender, SelectionChangedEventArgs e) 10 { 11 if (e.RemovedItems != null) 12 { 13 foreach (var item in e.RemovedItems.OfType<string>()) 14 { 15 PackageStore.RemovePackage(new Uri(System.IO.Path.GetFileName(item) + "://")); 16 } 17 } 18 19 20 21 if (e.AddedItems != null) 22 { 23 foreach (var item in e.AddedItems.OfType<string>()) 24 { 25 Stream fileMapViewStream; 26 try 27 { 28 //FileStream fs = File.Open(item.Replace("\\", ":"), FileMode.OpenOrCreate); 29 fileMapViewStream = MemoryMappedFile.OpenExisting(item.Replace("\\", ":"), MemoryMappedFileRights.Read).CreateViewStream(0, new FileInfo(item).Length, MemoryMappedFileAccess.Read); 30 } 31 catch(IOException) 32 { 33 fileMapViewStream = MemoryMappedFile.CreateFromFile(item, FileMode.Open, item.Replace("\\", ":"), new FileInfo(item).Length, MemoryMappedFileAccess.Read).CreateViewStream(0, new FileInfo(item).Length, MemoryMappedFileAccess.Read); 34 } 35 PackageStore.AddPackage(new Uri(System.IO.Path.GetFileName(item) + "://"), Package.Open(fileMapViewStream, FileMode.Open, FileAccess.Read)); 36 Application.Current.Resources.MergedDictionaries[0] = new ResourceDictionary() { Source = new Uri("pack://" + System.IO.Path.GetFileName(item) + ":,,,/ResourceDictionary.xaml") }; 37 } 38 } 39 }