WPF资源
WPF资源系统是一种保管一系列对象(如常用的画刷、样式或模版)的简单办法,从而使您更容易地复用这些对象。
WPF允许在代码中以及在标记中的各个位置定义资源(和特定的控件、窗口一起定义,或在整个应用程序中定义)。资源具有如下优点。
- 高效。定义好资源可以在多个地方复用。
- 可维护性。易于修改。
- 适应性。可以动态修改。
资源集合
每个元素都有Resources属性,该属性存储了一个资源字典集合(它是ResourceDictionary类的实例)。资源集合可包含任意类型的对象,并根据字符串编写索引。
<Window.Resources> <ImageBrush x:Key="TitleBrush" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32"ImageSource="" Opacity="0.3"></ImageBrush> </Window.Resources> <StackPanel> <Button Background="{StaticResource TitleBrush}">Requery</Button> </StackPanel>
资源的层次
每个元素都有自己的资源集合,为了找到期望的资源,WPF在元素树中进行递归搜索。
只要不在同一集合中多次使用相同的资源名,就可以重用资源名称。
<Window.Resources> <ImageBrush x:Key="TitleBrush" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32" ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush> </Window.Resources> <StackPanel> <Button Background="{StaticResource TitleBrush}">Requery</Button> <Button Background="{DynamicResource TitleBrush}"> <Button.Resources> <ImageBrush x:Key="TitleBrush" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32" ImageSource="abc.jpg" Opacity="0.3"></ImageBrush> </Button.Resources> <Button.Content>Another Titled Button</Button.Content> </Button> </StackPanel>
静态资源和动态资源
上面的代码设置后如果执行如下代码
ImageBrush brush=(ImageBrush)this.Resources["TitleBrush"]; brush.Viewport = new Rect(0,0,5,5);
上述代码从Window.Resources中检索画刷,并改变画刷平铺的尺寸,缩小笑脸图像并压缩图像模式使其更加紧凑。因为是静态资源正常上面的按钮是不会有变化,
但是这一变化会传递给上面的按钮,更新Viewport属性。这是因为Brush类继承自Freezable类。改类有一个基本变化跟踪特性。这意味着无论何时在WPF中改变画刷,所有使用该画刷的控件都会自动更新。静态资源和动态资源的区别在于静态资源只从资源集合中获取对象一次,动态资源每次需要对象时都会重新从资源集合中查找对象。例如:
this.Resources["TitleBrush"] = new SolidColorBrush(Colors.LightBlue);
执行如上代码,对于静态资源没影响,动态资源会发生变化。
使用动态属性的情况
- 资源具有依赖于系统设置的属性(如当前Windows操作系统的颜色或字体)。
- 准备通过编程的方式替换对象。(例如实现动态皮肤特性,后台会讲到)
非共享资源
正常情况下资源使用的是统一对象实例,这种行为成为共享,如果希望每次都创建一个新的对象可如下设置。x:Shared="False"
<ImageBrush x:Key="TitleBrush" x:Shared="False" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32" ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush>
通过代码访问资源
private void txt_TextChanged(object sender, RoutedEventArgs e) { Button cmd = (Button)sender; ImageBrush brush = (ImageBrush)cmd.FindResource("TitleBrush"); }
可使用TryFindResource()代替FindResource()。如果找不到资源会返回null,而不是抛异常。
应用程序资源
窗口不是查找应用程序资源的最后一站,如果在控件或其他容器中知道包含窗口或页面找不到指定的资源。WPF会继续查找为应用程序定义的资源。在Visual Studio中,这些资源在App.xaml文件的标记中定义的资源。
<Application x:Class="HelloWpf.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="GridDemoWindow.xaml"> <Application.Resources> <ImageBrush x:Key="TitleBrush" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32" ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush> </Application.Resources> </Application>
应用程序资源为整个应用程序中重用对象提供了一种极佳的方法。
系统资源
当某个元素查找资源时,应用程序资源仍然不是最后一站。如果没有在应用程序资源中找到所需的资源,元素还会继续查找系统资源。
系统资源的三个类
- SystemColors 访问系统颜色设置。
- SystemFonts 访问字体设置。
- SystemParamerers 封装了大量的设置列表,这些设置描述了各种屏幕像素的标准尺寸、键盘和鼠标设置、屏幕尺寸以及各种图形效果(如热跟踪、阴影以及拖动窗口时显示窗口内容)是否已经打开。
资源字典
如果希望多个项目中共享资源,可创建资源字典。资源字典只是xaml文档,除了存储希望使用的资源外,不做其他任何事情。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ImageBrush x:Key="TitleBrush" TileMode="Tile" ViewboxUnits="Absolute" Viewport="0 0 32 32" ImageSource="happyface.jpg" Opacity="0.3"></ImageBrush> </ResourceDictionary>
使用资源字典将其整合到应用程序资源中。
<Application x:Class="HelloWpf.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="GridDemoWindow.xaml"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="AppBrushs.xaml"></ResourceDictionary> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application>