【问题标题】:Silverlight Shared MergedDictionariesSilverlight 共享合并字典
【发布时间】:2010-11-11 09:31:42
【问题描述】:

我正在使用 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 中实例化一次?

【问题讨论】:

    标签: silverlight mergeddictionaries


    【解决方案1】:

    问题在于 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);
            }
        }
    

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

        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)});
    

    对于其他互不依赖的字典。

    【讨论】:

    • 很棒的解决方案,谢谢!我不得不将您的 LoadResource 调用更改为: LoadResource(new Uri("ProjectResources;component/Resources/Stylesheets/ComboBox.xaml", UriKind.Relative));当我尝试您的示例时,出现了不支持 Uri 的异常。此外,当它到位时,您会丢失 Blend 中的设计视图。我不是一个开发人员,所以我只是评论/取消评论 app.xaml 以设置样式。
    【解决方案2】:

    我能够调整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>
    

    【讨论】:

      【解决方案3】:

      如果加载时出错,请确保将构建操作设置为以下之一:

      //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));
      

      格雷格

      【讨论】:

        【解决方案4】:

        关于这个线程的另一个有趣的注释是,如果在两个不同的字典中找到一个样式,SL 只会保留一个副本。最后一个获胜。换句话说,如果您有两种不同的样式,它们都具有相同的键,则第一个在第二个加载时将被丢弃。

        【讨论】:

          猜你喜欢
          • 2020-12-12
          • 2016-06-20
          • 2012-10-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多