如何处理资源字典,因此他们不会创建不必要的对象

时间:2015-08-13 11:53:16

标签: wpf xaml resourcedictionary

我移动了一些常用于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个对象,但我也不想通过在很多地方复制和粘贴它来编写这些样式。

1 个答案:

答案 0 :(得分:2)

您可以执行以下操作:

  1. 将样式存储在工作目录或资源中的文件中(一种样式的一个文件)
  2. 创建类(例如ResourcesHolder),它将通过其Key为您提供资源(如FindResource一样)
  3. ResourcesHolder具有FindResource(string resourceName)方法:
    • 在资源中搜索与resourceName
    • 同名的文件
    • 使用XamlReader解析它并返回
  4. ResourcesHolder类包含存储已解析对象的Dictionary。要,如果已经解析了任何资源,您将从该字典中返回它:

    private Dictionary<string, object> storedObjects;
    
    public object FindResource(string resourceName)
    {
        if (storedObjects.ContainsKey(resourceName))
            return storedObjects[resourceName];
    
        else
            //search, parse and return new resource
    }
    

    因此,您可以单独加载每个资源而无需加载任何其他资源

  5. 修改

    在调用Initialize()方法之前,您可以加载创建窗口/用户控件所需的所有资源。在这种情况下,您可以向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)
            }
        }
    

    在你的控制/窗口中:

        public partial class TestWindow : Window
        {
            public TestWindow()
            {
                ResourceHolder.Load("SaveButtonStyle");
                ResourceHolder.Load("CloseButtonStyle");
                InitializeComponent();
            }
        }
    

    在您的xaml中,您可以使用{StaticResource}扩展名

    如果你想在xaml中自动执行,如{StaticResource}或{DynamicResource},你必须编写自己的markupextension,它将调用ResourceHolder本身的Load或FindResource方法