34

在单独的项目中定义 WPF 资源时,如何避免 Visual Studio 设计器错误?

我在复合 WPF 应用程序中有三个项目:主应用程序、“基础设施”库和“模块”库。主应用程序通过它们的输出 DLL 引用其他项目(这些项目不一起位于单个解决方案中)。

ResourceDictionary在“基础设施”库中定义了一个皮肤(a 中的一些画笔和样式)。我希望主应用程序选择一个皮肤并使其可用于整个应用程序(通过MergedDictionaries在 App.xaml 中)。

在我的模块中,我想使用主应用程序加载的皮肤中定义的资源。如果我引用该资源,就好像它在本地可用一样:

Background={StaticResource MainBackgroundBrush}

几乎一切都按预期工作。例外情况是 Visual Studio 的设计者感到困惑并告诉我“找不到静态资源引用‘MainBackgroundBrush’”。这有效地阻止了我使用设计器。

如何ResourceDictionary在项目中定义“皮肤”,在主应用程序中引用该皮肤,然后在模块项目中使用其资源?

4

3 回答 3

4

您可以创建自己的 ResourceDictionary 类,继承自 ResourceDictionary。然后您可以安排在设计时这个自定义 ResourceDictionary 加载一些明确定义的样式(即在运行时从应用程序加载的样式),而在运行时它什么也不做。可以为此评估 IsInDesignMode-Property。

假设您有这样一个类,称为“DesignTimeResourceDictionary”,那么您只需使用 s.th。像

 <UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <Util:DesignTimeResourceDictionary Source="SomeUriToYourResources"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
 </UserControl.Resources>

在设计时加载您的资源并使设计器工作。在运行时,您可以让您的 DesignTimeResourceDictionary 跳过资源加载并实现所需的行为。

如果需要,您可以真正为此创建真实资源的副本,或者您可以创建一个虚拟字典,其中包含保持设计器工作所需的所有键。

于 2009-07-10T19:21:03.857 回答
3

一种可能的解决方案是使用DynamicResource而不是StaticResource. Visual Studio 2008 设计器只显示控件而没有任何样式,就像 VS2010 beta 1 在无法解析StaticResource.

UsingDynamicResource适用于特定样式可能在运行时发生变化的情况,例如换肤时。

我发现了一些支持这一点的相关问题:

我还发现有人指出,DynamicResource只要资源不是本地的,就应该使用它:

于 2009-07-09T21:36:25.893 回答
2

我只想扩展 Simon D. 的答案。他提出的是我现在正在使用的解决方案。我只是想分享完整的源代码。仅在设计模式源中使用 ResourceDictionary 的技巧来自此技巧。

public class DesignTimeResourceDictionary : ResourceDictionary
{
    /// <summary>
    /// Local field storing info about designtime source.
    /// </summary>
    private string designTimeSource;

    /// <summary>
    /// Gets or sets the design time source.
    /// </summary>
    /// <value>
    /// The design time source.
    /// </value>
    public string DesignTimeSource
    {
        get
        {
            return this.designTimeSource;
        }

        set
        {
            this.designTimeSource = value;
            if ((bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue)
            {
                base.Source = new Uri(designTimeSource);
            }
        }
    }

    /// <summary>
    /// Gets or sets the uniform resource identifier (URI) to load resources from.
    /// </summary>
    /// <returns>The source location of an external resource dictionary. </returns>
    public new Uri Source
    {
        get
        {
            throw new Exception("Use DesignTimeSource instead Source!");
        }

        set
        {
            throw new Exception("Use DesignTimeSource instead Source!");
        }
    }
}

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation Jump "
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml Jump "
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:WpfApplication1">

  <Window.Resources>
    <local:DesignTimeResourceDictionary DesignTimeSource="pack://application:,,,/BlueColors.xaml"/>
  </Window.Resources>

    <Grid>
      <Button Background="{DynamicResource defaultBackground}"
      HorizontalAlignment="Center" VerticalAlignment="Center">click me</Button>
    </Grid>
</Window>
于 2017-07-21T15:17:40.003 回答