如何在另一个库中引用定义在单独程序集中的WPF样式键

14
我有两个库和一个单一的应用程序集项目布局,我想知道如何通过其键引用其中一个库中定义的样式来实现我的另一个库。
我的解决方案布局: - WpfControls.dll - 包含通用可重用控件,例如基于WPF的NumericUpDown控件以及其他基本控件和一些样式,我希望这些样式可以重复使用。 - SpecializedControls.dll- 包含专门针对我们应用程序的控件,例如自定义复合控件和WPF中的UserControls。在这里我想引用WpfControls.dll程序集中定义的MyButtonStyle样式。 - Application.exe - 此程序集使用SpecializedControls.dll程序集中定义的控件。
我看过一些例子,说明如何在简单的单个控件库和应用程序集中实现此操作,但在我的情况下,我有两个库和一个应用程序。因此,在我的情况下,我的第二个控件库中没有App.xaml,我可以在其中使用MergeDictionaries概念。我相当确定如果我愿意,我可以在每个控件的XAML文件中直接放置MergedDictionaries引用,以将WpfControls.dll程序集中定义的Generic.xaml合并成一个,但我的猜测是,这将导致样式被多余地合并到SpecializedControls程序集的各个位置,这似乎不是最佳解决方案。更糟糕的是,这些字典也可能合并到Application.exe中,这会开始膨胀我的应用程序在运行时吗?
有人可以澄清使用最少量的编程和资源开销共享此类样式的推荐或最佳方法吗?
更新:经过更多测试,似乎我无法通过其键引用在Generic.xaml中定义的任何资源,即使在同一程序集中也是如此。关于我如何理解资源键是否有完全错误的地方,因此我将需要进行更多的研究,并查看ComponentResourceKey。如果有任何提示或建议,请帮忙。
2个回答

16

WPF中的资源查找按照层级顺序进行:从逻辑树向上查找,然后是应用程序资源、主题资源和最后是系统资源。

通常情况下,主题资源只能隐式访问(即使在定义它们的程序集内部也是如此)。这仅与样式相关,在其中TargetType可以用作隐式键。

要实现你想做的事情,有两个选项:

  • 使用ComponentResourceKey。这是一种特殊的资源键,允许引用其他程序集中的资源。例如,您可以在WpfControls主题字典中定义一个画刷:

    <LinearGradientBrush x:Key="{ComponentResourceKey TypeInTargetAssembly=local:MyClass, ResourceId=MyBrush}">
        <GradientStop Color="Red" />
        <GradientStop Color="Blue" Offset="1" />
    </LinearGradientBrush>
    

    然后您可以在SpecializedControls中引用它:

    <UserControl Background="{StaticResource {ComponentResourceKey TypeInTargetAssembly=wpfControls:MyClass, ResourceId=MyBrush}}" />
    
    使用MergedDictionaries将字典导入应用程序资源。您可以在Application程序集中执行此操作,当应用程序加载时,即使在SpecializedControls中的控件也能够使用这些资源。在这种情况下,您将遇到设计时体验问题,您可以通过在SpecializedControls中放置一个虚拟的App.xaml来解决该问题,该文件还包含对字典的引用。

4
我面临着相同的问题。您能否请详细说明第二个选项?例如,如何使用MergedDictionary声明基于另一个程序集中声明的样式的样式,我不明白它的工作原理。 - JoanComasFdz
谢谢您提供“伪造App.xaml”的提示。这对于使用MergedDictionaries技术非常重要。 - Pete Magsig

1

已经接受的答案是正确的,我只是解释如何使用 MergedDictionaries

App.xaml 中,

    <Application.Resources>
      <ResourceDictionary>
         <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/-YourDllName-;component/-DirectoryName-/FileName.xaml"/>
            <!-- Use Below syntax if your resource file is not inside a directory(in root) -->
            <ResourceDictionary Source="pack://application:,,,/-YourDllName-;component/FileName.xaml"/>
         </ResourceDictionary.MergedDictionaries>
      </ResourceDictionary>
    </Application.Resources>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接