Silverlight Shared MergedDictionaries

时间:2010-11-11 09:31:42

标签: silverlight mergeddictionaries

我正在使用Silverlight 4并试图分享一些常见的样式(颜色,画笔)。 我的看法是将它们放入“Common.xaml”资源字典中,然后在所有其他资源字典中使用它。 引用所有内容:

<Application 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  x:Class="SampleApp.App"
>
  <Application.Resources>

    <ResourceDictionary>

      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Assets/Styles/Common.xaml"/>
        <ResourceDictionary Source="Assets/Styles/TextBoxStyle.xaml"/>
      </ResourceDictionary.MergedDictionaries>

    </ResourceDictionary>

  </Application.Resources>

</Application>

问题是,我在InitializeComponent上遇到异常,说明找不到常见样式(找不到名称/密钥的资源......)

我必须在我使用它的每个资源字典中显式引用“Common.xaml”....这基本上导致每个颜色,画笔,模板和诸如“Common.xaml”中的诸如内容的多个实例

没有任何方法可以共享资源,因此只能在Silverlight中获得一次实现吗?

4 个答案:

答案 0 :(得分:4)

问题在于Silverlight似乎简化了资源字典的加载,因此可以并行加载多个字典。因此,当一个字典依赖于另一个字典时,依赖关系可能无法及时准备好。

由于ResourceDictionary没有内置的方法来描述相互依赖关系,也没有一个事件来指示它何时加载了我能够实现的唯一解决方案是自己管理字典的加载。

这是一个可以添加到App.xaml.cs文件中以“手动”加载资源字典的函数: -

    private void LoadResource(Uri uri)
    {
        var info = Application.GetResourceStream(uri);
        string xaml;
        using (var reader = new StreamReader(info.Stream))
        {
            xaml = reader.ReadToEnd();
        }

        ResourceDictionary result = XamlReader.Load(xaml) as ResourceDictionary;

        if (result != null)
        {
            Resources.MergedDictionaries.Add(result);
        }
    }

现在在Application_Startup分配RootVisual之前,您将使用以下代码: -

    LoadResource(new Uri"Assets/Styles/Common.xaml", UriKind.Relative));
    LoadResource(new Uri("Assets/Styles/TextBoxStyle.xaml", UriKind.Relative));

它不会像使用Source属性那样高效,但它会起作用。如果你有很多这样的词典,只有很少的“常用”词典包含共享资源,那么你可以使用这种技术只加载“常用”词典然后使用: -

Resource.MergedDictionaries.Add(new ResourceDictionary() {Source = new Uri("Assets/Styles/TextBoxStyle.xaml", UriKind.Relative)});

对于彼此没有相互依赖关系的其他词典。

答案 1 :(得分:1)

我能够调整http://www.wpftutorial.net/MergedDictionaryPerformance.html中提出的解决方案 使其适用于Silverlight和VS设计师(尚未尝试过Blend)。我在这里有一篇博文(http://softnotes.wordpress.com/2011/04/05/shared-resourcedictionary-for-silverlight/

public class SharedResourceDictionary : ResourceDictionary
{
    public static Dictionary<Uri, ResourceDictionary> _sharedDictionaries =
       new Dictionary<Uri, ResourceDictionary>();

    private Uri _sourceUri;
    public new Uri Source
    {
        get { return _sourceUri; }
        set
        {
            _sourceUri = value;
            if (!_sharedDictionaries.ContainsKey(value))
            {
                Application.LoadComponent(this, value);
                _sharedDictionaries.Add(value, this);
            }
            else
            {
                CopyInto(this, _sharedDictionaries[value]);
            }
        }
    }

    private static void CopyInto(ResourceDictionary copy, ResourceDictionary original)
    {
        foreach (var dictionary in original.MergedDictionaries)
        {
            var mergedCopy = new ResourceDictionary();
            CopyInto(mergedCopy, dictionary);
            copy.MergedDictionaries.Add(mergedCopy);
        }
        foreach (DictionaryEntry pair in original)
        {
            copy.Add(pair.Key, pair.Value);
        }
    }
}

XAML用法:

<ResourceDictionary.MergedDictionaries>
    <ui:SharedResourceDictionary Source="/my_assembly_name;component/Resources/Shared.xaml"/>
</ResourceDictionary.MergedDictionaries>

答案 2 :(得分:0)

如果加载错误,请确保将Build Action设置为以下之一:

//In the dll, which is in the xap, marked as Build Action: Resource or Page
LoadResource(new Uri("SilverlightApplication48;component/GlobalAssets.xaml", UriKind.Relative));

//In the xap at the same level as the dll, (not in the dll) marked as Build Action: Content.
LoadResource(new Uri("Dictionary1.xaml", UriKind.Relative));

//In a separate library, marked as Build Action: Resource or Page.
LoadResource(new Uri("StylesLibrary;component/Dictionary2.xaml", UriKind.Relative));

格雷格

答案 3 :(得分:0)

关于这个帖子的另一个有趣的注意事项是,如果在两个不同的词典中找到它,SL只保留一个样式的副本。最后一个获胜。换句话说,如果你有两个不同的样式都使用相同的键,第一个样式将在第二个加载时被丢弃。