这篇将介绍使用DynamicResource实现动态的界面切换功能。熟悉WPF的园友应该已经猜到了实现方式,简而言之就是动态替换DataTemplate,ControlTemplate,Style等等UI相关的属性。

那么使用DynamicResource能让UI动态到什么程度呢?可以说,心有多大,就可以做多大,只要你想得到,就可以做出来。

下面以展示层次数据结构为例,实现了运行时切换数据显示界面结构的功能。先来看一下要显示的数据,是一个XML文件。

<earth>
  <country name="US">
    <family name="Bill's">
      <member name="Bill"/>
      <member name="Mark"/>
    </family>
    <family name="Hugo's">
      <member name="Hugo"/>
      <member name="Sherry"/>
    </family>
    <family name="Li's">
      <member name="Li"/>
      <member name="Jay"/>
    </family>
  </country>
  <country name="China">
    <family name="陆家">
      <member name="嘴"/>
      <member name="脸"/>
    </family>
    <family name="徐家">
      <member name="汇"/>
      <member name="仁"/>
    </family>
    <family name="黄浦">
      <member name="江"/>
      <member name="边"/>
    </family>
  </country>
</earth>

我们要用三种方式来展示这个数据,一种是最常见的TreeView,还可以用一组并列的ListBox,还有不太常见的嵌套式ItemsControl。如下图所示。

图1. TreeView

图2. ListView

图3. GroupView

要实现这些效果,可以使用DataTemplate。把界面中会变的部分独立出来,有人说这个界面除了上面的菜单不变,整个都在变啊。没错,那就把整个主体部分独立出来,放到DataTemplate里。而Window里就只有一个菜单和一个占位符了。如下所示。

<Window x:Class="Skinning.DemoWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="View Demo" Height="300" Width="300">
    <DockPanel DataContext="{Binding Source={StaticResource XMLDataDataSource}}">
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="List View" Click="OnListViewClick"/>
            <MenuItem Header="Group View" Click="OnGroupViewClick"/>
            <MenuItem Header="Tree View" Click="OnTreeViewClick"/>
        </Menu>
        <ContentPresenter Content="{Binding}" ContentTemplate="{DynamicResource EarthDataTemplate}"/>
    </DockPanel>
</Window>

然后就是定义上面引用到的EarthDataTemplate。以ListView的DataTemplate为例,如下所示。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <DataTemplate x:Key="NameTemplate">
        <TextBlock Text="{Binding XPath=@name}"/>
    </DataTemplate>
    <DataTemplate x:Key="EarthDataTemplate">
        <UniformGrid Rows="1" DataContext="{Binding XPath=earth/country}">
            <ListBox ItemsSource="{Binding Mode=Default}" x:Name="countryList" ItemTemplate="{StaticResource NameTemplate}"/>
            <ListBox DataContext="{Binding SelectedItem, ElementName=countryList}"
                     ItemsSource="{Binding Mode=OneWay, XPath=family}"
                     x:Name="familyList" ItemTemplate="{StaticResource NameTemplate}"/>
            <ListBox DataContext="{Binding SelectedItem, ElementName=familyList}"
                     ItemsSource="{Binding Mode=OneWay, XPath=member}"
                     ItemTemplate="{StaticResource NameTemplate}"/>
        </UniformGrid>
    </DataTemplate>
</ResourceDictionary>

其它的DataTemplate就不一一例出了,完整的程序可以从这里下载。

虽然这个例子中只是展示了界面结构上的变化,只使用了DataTemplate,其它的小Case的形式的界面也完全不在话下。比如配色、控件样式、控件位置,乃至所谓的换肤,可以分解为这些技巧的组合。当你把DynamicResource、Style、TemplateSelector、Converter、MarkupExtension等各种WPF技术都用上的时候就会发现WPF可以提供很强大的界面生成功能。

再来介绍一下这种方式的缺点。

为什么微软的文档和WPF的相关书籍中都没有介绍这种方法呢?就像上一篇关于语言支持里列举的现有方案一样,都是要Build进DLL中呢? 我想其中一个原因就是安全上的考虑。把XAML文件这样赤祼 祼地放在外面,对于了解WPF的人来说,完全可以利用这个文件“执行任意代码”。这个很眼熟吧,常常出现在微软的各个安全补丁的描述中。而且一般会是严重的漏洞。

这个问题虽然严重,但也是基本可以解决的。像Web中各种Editor一样,可以对XAML里的内容,过滤一下,替换一下,限制一下等等。如果还不放心,可以把自己定义XML格式来定义界面,然后在内部用XSLT转成XAML再加载。对自定义的XML加限制会更容易些。

这篇内容比较简单,不过是为了下篇主要内容打个基础。下篇将要展示一个自定义的Window的Style,把WPF的WinForm式的边框去掉。

WPF中使用DynamicResource实现换肤的更多相关文章

  1. 在WPF中创建可换肤的用户界面

    原文:在WPF中创建可换肤的用户界面 在WPF中创建可换肤的用户界面.                                                                  ...

  2. 解决duilib使用zip换肤卡顿的问题(附将资源集成到程序中的操作方法)

    转载请说明原出处,谢谢~~ 今天在做单子是.客户要求做换肤功能,为此我专门写了一个换肤函数,而且把各种皮肤资源压缩为各个zip文件来换肤.可是客户反映程序执行缓慢,我測试后发现的确明显能够看出慢了不少 ...

  3. 解决duilib使用zip换肤卡顿的问题:修改duilib并使用资源文件换肤

    转载请说明原出处,谢谢~~ 今天在做单子是,客户要求做换肤功能,为此我专门写了一个换肤函数,并且把各种皮肤资源压缩为各个zip文件来换肤.但是客户反映程序运行缓慢,我测试后发现的确明显可以看出慢了不少 ...

  4. Android动态换肤(一、应用内置多套皮肤)

    动态换肤在很多android应用中都有使用,用户根据自己的喜好设置皮肤主题,可以增强用户使用应用的舒适度. Android换肤可以分为很多种,它们从使用方式,用户体验以及项目框架设计上体现了明显的差异 ...

  5. Scss换肤

    项目中虽然没有一键换肤的要求,但是产品要求后期能换主题.在开发组件中涉及到主题的地方,要提取一些公用的变量,不要直接写死样式值.但是如果只是定义一些变量的话,只是完成控制颜色等值的提取.后期切换的话需 ...

  6. vue+ element 动态换肤

    转至 https://www.cnblogs.com/dengqichang/p/10364455.html 一.搭建好项目的环境. 二.根据ElementUI官网的自定义主题(http://elem ...

  7. WPF换肤之三:WPF中的WndProc

    原文:WPF换肤之三:WPF中的WndProc 在上篇文章中,我有提到过WndProc中可以处理所有经过窗体的事件,但是没有具体的来说怎么可以处理的. 其实,在WPF中,要想利用WndProc来处理所 ...

  8. WPF之换肤

    WPF之换肤 设计原理 WPF换肤的设计原理,利用资源字典为每种皮肤资源添加不同的样式,在后台切换皮肤资源文件. 截图 上图中,第一张图采用规则样式,第二张图采用不规则样式,截图的时候略有瑕疵. 资源 ...

  9. 有点激动,WPF换肤搞定了!

    一如既往没废话! wpf桌面应用开发都是window内引入很多个UserControl. 如果你有通过不同颜色来换肤的需求,那么下面我就将整个过程! 分2个步骤: 1.主窗体背景色替换: 2.同时界面 ...

随机推荐

  1. NFS

    测试版本:CentOS 6.4 64b NFS监听2049(TCP/UDP)端口,但由于文件系统非常复杂,不同的功能都会使用不同的程序来启动,因此额外端口就会不固定(随机1024以下的),这就需要向远 ...

  2. Android之分页加载数据

    基本的原理和我的上一篇随笔“Android之下拉刷新ListView”差不多,代码里面有注释,这里就不废话了,直接上代码. 自定义的分页显示ListView——PagedListView.java代码 ...

  3. easyUI中onLoadSuccess方法获取多个对象

    后台将一个list中的对象循环放到map中,如下: @RequestMapping("/getSaleOrderDetailList") @ResponseBody public ...

  4. Qt - 错误总结 - 在自定义类头文件中添加Q_OBJECT 编译时报错(undefined reference to ‘vtable for xxThread)

    错误提示:在添加的QThread子类头文件添加Q_OBJECT时,编译程序,出现"undefined reference to 'vtable for xxThread'"错误提示 ...

  5. 详解SpringMVC中GET请求

    GET请求概述 GET请求,请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接.URL的编码格式采用的是ASCII编码,而不是uniclde,所有的非ASCII字符都要编 ...

  6. gen_server port 调用receive_match 问题

    问题由来 前些天对系统做了一个优化,将原来从queue 轮询刷出数据后每条消息一个 spawn 进程单独处理,修改为批量刷出.一条一条刷轮询刷 queue 存在问题:刷queue 进程太多时,占用CP ...

  7. git 命令熟悉

    1. git clone +ssh 地址=将远程代码download 到本地:要在根目录执行这个操作 2.查看所有分支:git branch -a (当前分支前带星号) 3.切换到某个分支:git c ...

  8. ACM/ICPC 之 三维计算几何+暴力枚举+判重(HDU5839)

    CCPC网赛第八题,求立体几何数量,题解见注释 //立体几何-求满足要求的四面体个数 //要求1:至少4条边相等 //要求2:四条边相等时,另两条边一定不相邻(即对边) //题解:以当前边为不相邻的其 ...

  9. SAP 直营验单

    *&---------------------------------------------------------------------* *& Report  ZSDR005 ...

  10. C/C++: C++可调用对象详解

    C++中有几种可调用对象:函数,函数指针,lambda表达式,bind创建的对象,以及重载了函数调用符的类. 1. 函数 函数偏基础的东西,在这里不再叙述.重点讲下C++11的某些重要特性和函数指针. ...