WPF SharedResourceDictionary

时间:2012-01-03 12:22:04

标签: wpf resources

我使用自定义类在我的WPF应用程序中实现共享资源功能这是一个用于创建和管理词典的示例代码

public class SharedResourceDictionary : ResourceDictionary
{
    /// <summary>
    /// Internal cache of loaded dictionaries 
    /// </summary>
    public static Dictionary<Uri, ResourceDictionary> SharedDictinaries = new Dictionary<Uri, ResourceDictionary>();

    /// <summary>
    /// Local member of the source uri
    /// </summary>
    private Uri _sourceUri;

    private static bool IsInDesignMode
    {
        get
        {
            return (bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty,
                                                                   typeof(DependencyObject)).Metadata.DefaultValue;
        }
    }

    /// <summary>
    /// Gets or sets the uniform resource identifier (URI) to load resources from.
    /// </summary>
    public new Uri Source
    {
        get
        {
            if (IsInDesignMode)
            {
                return base.Source;
            }
            return _sourceUri;
        }
        set
        {
            if (!IsInDesignMode)
            {
                base.Source = value;
                return;
            }
            _sourceUri = value;
            if (!SharedDictinaries.ContainsKey(value))
            {
                base.Source = value;
                SharedDictinaries.Add(value, this);
            }
            else
            {
                MergedDictionaries.Add(SharedDictinaries[value]);
            }
        }
    }
}

这个文件是在一个单独的程序集中实现的,我在我的shell WPF应用程序中对它进行了引用。

我的app.xaml中定义了我的资源以下列方式

    <Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <Infrastructure:SharedResourceDictionary Source="pack://application:,,,/CuratioCMS.Client.Resources;Component/Themes/General/Brushes.xaml" />
            <Infrastructure:SharedResourceDictionary Source="pack://application:,,,/Fluent;Component/Themes/Office2010/Silver.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
   </Application.Resources>

如果我删除Brushes.xaml它可以正常工作,但是当我切换到设计视图时,我会得到以下错误

调用目标抛出了异常

有人可以帮助我找出问题吗?

3 个答案:

答案 0 :(得分:3)

为了解决这个问题,我做了(我真的很想在VisualStudio 2010的设计时工作):

    public string SourcePath { get; set; }

    public new Uri Source
    {
        get
        {
            if (IsInDesignMode)
            {
                return base.Source;
            }
            else
            {
                return _sourceUri;
            }

        }
        set
        {
            if (value == null)
                return;

            if (IsInDesignMode)
            {
                var dict = Application.LoadComponent(new Uri(SourcePath, UriKind.Relative)) as ResourceDictionary;
                MergedDictionaries.Add(dict);
                return;
            }

            _sourceUri = value;
            if (!_sharedDictionaries.ContainsKey(value))
            {
                base.Source = value;

                _sharedDictionaries.Add(value, this);
            }
            else
            { 
                MergedDictionaries.Add(_sharedDictionaries[value]);
            }
        }
    }

在我的XAML中:

<SharedResourceDictionary SourcePath="JooThemes;component/Buttons/Small/SettingsToggleStyle.xaml" Source="/JooThemes;component/Buttons/Small/SettingsToggleStyle.xaml" />

答案 1 :(得分:0)

我在某处读到,这是一个内存问题@ design-time。我在Setter of Source中解决了这个问题:

    /// <summary>
    /// Gets or sets the uniform resource identifier (URI) to load resources from.
    /// </summary>
    public new Uri Source
    {
        get { return _sourceUri; }
        set
        {
            _sourceUri = value;
            if (!_sharedDictionaries.ContainsKey(value))
            {
                try
                {
                     //If the dictionary is not yet loaded, load it by setting
                     //the source of the base class
                    base.Source = value;
                }
                catch (Exception exp)
                {
                    //only throw exception @runtime to avoid "Exception has been 
                    //thrown by the target of an invocation."-Error@DesignTime
                    if( ! IsInDesignMode )
                        throw;
                }
                // add it to the cache
                _sharedDictionaries.Add(value, this); 
            }
            else
            {
                // If the dictionary is already loaded, get it from the cache 
                MergedDictionaries.Add(_sharedDictionaries[value]); 
            }                 
        }
    }

答案 2 :(得分:0)

我知道这个问题已经解决了,但是由于我一直在与朋友一起寻求替代解决方案,因此我想与大家分享:
1.在xaml中的任何地方都使用WPF ResourceDictionary,这样Blend和VS设计器就不会损坏。
2.参考nuget软件包Sundew.Xaml.OptimizationsSundew.Xaml.Optimizer
3.在项目的根目录中添加sxo-settings.json并启用ResourceDictionaryCachingOptimizer
4.构建
构建将使用缓存/共享的ResourceDictionary。

有关更多详细信息,请参见:https://github.com/hugener/Sundew.Xaml.Optimizations
和示例: https://github.com/hugener/Sundew.Xaml.Optimizer.Sample