如何处理资源字典,以免它们创建不必要的对象
How to deal with Resource Dictionaries, so they don't create unnecessary objects
我将一些常用的资源移到了 ResourceDictionary,例如
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="SaveButtonStyle" TargetType="{x:Type Button}">
<Setter Property="IsDefault" Value="True" />
<Setter Property="IsCancel" Value="False" />
<Setter Property="ToolTip" Value="Close and save any changes you have made." />
</Style>
<Style x:Key="CloseButtonStyle" BasedOn="{StaticResource XSaveCloseButtonStyle}" TargetType="{x:Type Button}">
<Setter Property="IsDefault" Value="False" />
<Setter Property="IsCancel" Value="True" />
<Setter Property="ToolTip" Value="Close window." />
</Style>
</ResourceDictionary>
原因很简单,我需要在多个地方使用相同的样式。但是我发现了一个问题,如果某个地方我只需要使用 CloseButtonStyle,我会引用这个资源字典。我认为它创建了两种样式,我做了一些测试,并通过 FindResource 方法查看了后面的代码,看看我是否会获得每种样式的实例,我确实做到了。
所以我的问题是我该如何处理呢?如果我只需要一个对象,我不想创建 2 个对象,但我也不想通过在很多地方复制和粘贴来编写这种样式。
您可以执行以下操作:
- 将样式存储在工作目录或资源中的文件中(一个文件对应一种样式)
- 创建 class(例如 ResourcesHolder),它将通过其键为您提供资源(就像 FindResource 那样)
- ResourcesHolder 具有 FindResource(string resourceName) 方法:
- 在资源中搜索与 resourceName 同名的文件
- 使用 XamlReader 和 returns
对其进行解析
ResourcesHolder class 包含存储解析对象的字典。要,如果任何资源已经被解析,你将从这个字典中return它:
private Dictionary<string, object> storedObjects;
public object FindResource(string resourceName)
{
if (storedObjects.ContainsKey(resourceName))
return storedObjects[resourceName];
else
//search, parse and return new resource
}
因此,您可以单独加载每个资源而无需加载任何其他内容
编辑:
在调用 Initialize() 方法之前,您可以加载创建 window/usercontrol 所需的所有资源。在这种情况下,您可以将方法添加到 ResourceHolder:
public void Load(string resourceName)
{
if (Application.Current.Resources.Contains(resourceName))
return;
else
{
var obj = /*load your resource here*/;
Application.Current.Resources.Add(resourceName, obj)
}
}
在你的control/window中:
public partial class TestWindow : Window
{
public TestWindow()
{
ResourceHolder.Load("SaveButtonStyle");
ResourceHolder.Load("CloseButtonStyle");
InitializeComponent();
}
}
在这种情况下,在您的 xaml 中,您可以使用 {StaticResource} 扩展程序
如果您想在 xaml 中自动执行此操作,例如 {StaticResource} 或 {DynamicResource},您将必须编写自己的标记扩展来调用 ResourceHolder 本身的 Load 或 FindResource 方法
我将一些常用的资源移到了 ResourceDictionary,例如
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="SaveButtonStyle" TargetType="{x:Type Button}">
<Setter Property="IsDefault" Value="True" />
<Setter Property="IsCancel" Value="False" />
<Setter Property="ToolTip" Value="Close and save any changes you have made." />
</Style>
<Style x:Key="CloseButtonStyle" BasedOn="{StaticResource XSaveCloseButtonStyle}" TargetType="{x:Type Button}">
<Setter Property="IsDefault" Value="False" />
<Setter Property="IsCancel" Value="True" />
<Setter Property="ToolTip" Value="Close window." />
</Style>
</ResourceDictionary>
原因很简单,我需要在多个地方使用相同的样式。但是我发现了一个问题,如果某个地方我只需要使用 CloseButtonStyle,我会引用这个资源字典。我认为它创建了两种样式,我做了一些测试,并通过 FindResource 方法查看了后面的代码,看看我是否会获得每种样式的实例,我确实做到了。 所以我的问题是我该如何处理呢?如果我只需要一个对象,我不想创建 2 个对象,但我也不想通过在很多地方复制和粘贴来编写这种样式。
您可以执行以下操作:
- 将样式存储在工作目录或资源中的文件中(一个文件对应一种样式)
- 创建 class(例如 ResourcesHolder),它将通过其键为您提供资源(就像 FindResource 那样)
- ResourcesHolder 具有 FindResource(string resourceName) 方法:
- 在资源中搜索与 resourceName 同名的文件
- 使用 XamlReader 和 returns 对其进行解析
ResourcesHolder class 包含存储解析对象的字典。要,如果任何资源已经被解析,你将从这个字典中return它:
private Dictionary<string, object> storedObjects; public object FindResource(string resourceName) { if (storedObjects.ContainsKey(resourceName)) return storedObjects[resourceName]; else //search, parse and return new resource }
因此,您可以单独加载每个资源而无需加载任何其他内容
编辑:
在调用 Initialize() 方法之前,您可以加载创建 window/usercontrol 所需的所有资源。在这种情况下,您可以将方法添加到 ResourceHolder:
public void Load(string resourceName)
{
if (Application.Current.Resources.Contains(resourceName))
return;
else
{
var obj = /*load your resource here*/;
Application.Current.Resources.Add(resourceName, obj)
}
}
在你的control/window中:
public partial class TestWindow : Window
{
public TestWindow()
{
ResourceHolder.Load("SaveButtonStyle");
ResourceHolder.Load("CloseButtonStyle");
InitializeComponent();
}
}
在这种情况下,在您的 xaml 中,您可以使用 {StaticResource} 扩展程序
如果您想在 xaml 中自动执行此操作,例如 {StaticResource} 或 {DynamicResource},您将必须编写自己的标记扩展来调用 ResourceHolder 本身的 Load 或 FindResource 方法