WPF之Resource
Resource
WPF资源系统是一种保管一系列有用对象(如常用的画刷、样式或模板)的简单方法,从而使您可以更容易地重用这些对象。
注:不要将WPF对象资源与程序集资源混为一谈。程序集资源是一块嵌入到编译过的程序集中的二进制数据。使用程序集资源可以确保应用程序具有其所需的图像或声音文件。另一方面,对象资源是希望在某个位置定义并在其他几个位置重复使用的.NET对象。
1、资源基础
WPF允许在代码中以及在标记中的各个位置定义资源(和特定的控件、窗口一起定义,或在整个应用程序中定义)。
- 高效,可重复使用,精简代码,更加高效
- 可维护,在Xaml中创建资源相当于在代码中创建常量
- 适应性强
1.1、资源集合
每个元素都有Resourcess属性,该属性存储了一个资源字典集合(它是ResourceDictionary类的实例)。资源集合可包含任意类型的对象,并根据字符串编写索引。
<Window.Resources>
<ImageBrush x:Key="TileBrush" TileMode="Tile"
ViewportUnits="Absolute" Viewport="0 0 32 32"
ImageSource="happyface.jpg" Opacity="0.3">
</ImageBrush>
</Window.Resources>
使用该资源:动态和静态
使用静态资源是,必须总是在引用资源之前的标记中定义资源。
<Button Background="{StaticResource TileBrush}">A Tiled Button</Button>
<Button Background="{DynamicResource TileBrush}">A Tiled Button</Button>
1.2、资源的层次
元素会先从自己的资源集合中开始查找指定的资源名。所以对于两个同名的资源,如果在子元素中定义了与父级元素同样的名称的资源是允许的,并且子元素会优先使用自己的资源。
1.3、静态资源和动态资源
StaticResource和DynamicResource有什么区别?
区别在于静态资源只从资源集合中获取对象一次。根据对象的类型(以及使用对象的方式),对象的任何变化都可能被立即注意到。然而,动态资源在每次需要对象时都会重新从资源集合中查找对象。这意味着可以在同一键下放置一个全新的对象,而且动态资源会应用该变化。
this.Resource["TileBrush"] = new SolidColorBrush(Color.LightBlue);
动态资源会应用该变化,而静态资源不知道它的画刷已在Resources集合中被其他内容替换了,它仍然继续使用原来的ImageBrush。
一般情况下,不需要使用动态属性,因为比较消耗性能,在下面的情况里需要使用DynamicResource
- 资源具有依赖于系统设置的属性(如当前Windows操作系统的颜色或字体)
- 准备通过编程方式替换资源对象(例如,实现几类动态皮肤特性)
1.4、通过代码访问资源
可以使用FrameworkElement.FindResource()方法以相同的方式查找资源,下面的代码是一个示例
private void cmd_Click(object sender, RoutedEventArgs e)
{
Button cmd = (Button)sender;
ImageBrush brush = (ImageBrush)cmd.FindResource("TileBrush");
}
1.5、应用程序资源
窗口不是查找资源的最后一站。如果在控件或其容器中(直到包含窗口或页面)找不到指定的资源,WPF会继续检查为应用程序定义的资源集合。在VS中,这些资源是在App.xaml文件的标记中定义的资源。
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ImageBrush x:Key="TileBrush" TileMode="Tile"
ViewportUnits="Absolute" Viewport="0 0 32 32"
ImageSource="happyface.jpg" Opacity="0.3">
</ImageBrush>
</Application.Resources>
</Application>
当某个元素查找资源时,应用程序资源仍然不是最后一站。如果没有在应用程序资源中找到所需的资源,元素还会继续查找系统资源。
1.6、资源字典
<Application x:Class="StoryEditor.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup"
DispatcherUnhandledException="Application_DispatcherUnhandledException">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resource/String/zh-CN.xaml" />
<ResourceDictionary Source="/Resource/TelerikLocalization/RadControl.zh-CN.xaml" />
<ResourceDictionary Source="/Resource/Value/Dim.xaml" />
<ResourceDictionary Source="/Resource/Value/Color.xaml" />
<ResourceDictionary Source="/Resource/Value/Style.xaml" />
<ResourceDictionary Source="/Resource/Value/Validation.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
在程序集中共享资源:切换主题的示例
public void ChangeTheme(string theme)
{
if (String.IsNullOrEmpty(theme))
{
return;
}
List<string> requestedTheme = null;
if (theme.Contains("dark"))
{
requestedTheme = new List<string>() {
@"/Telerik.Windows.Themes.Green;component/Themes/Telerik.Windows.Controls.xaml" ,
};
}
else if (theme.Contains("light"))
{
requestedTheme = new List<string>() {
@"/Telerik.Windows.Themes.Office2016;component/Themes/Telerik.Windows.Controls.xaml" ,
};
}
if (requestedTheme != null && requestedTheme.Count > 0)
{
RemoveAllThemeRes();
foreach (var rc in requestedTheme)
{
Resources.MergedDictionaries.Add(
new ResourceDictionary() { Source = new Uri(rc, UriKind.Relative) });
}
Settings.Default.Theme = theme;
Settings.Default.Save();
}
}

浙公网安备 33010602011771号