【问题标题】:WPF merged resource dictionaries in every user control - bad idea?WPF 在每个用户控件中合并资源字典 - 坏主意?
【发布时间】:2016-10-07 04:16:07
【问题描述】:

我将应用程序的资源保存在单独的 DLL 中,并在我的主 EXE 中使用 App.xaml 中的类似内容引用它们:-

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="pack://application:,,,/MyThemesAssembly;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>

当我编辑主 EXE 项目中的窗口时,VS2010 设计器无法识别来自其​​他程序集的任何资源,因此我看不到应用了任何样式(这不是真正的问题,因为我总是在 XAML 中工作看法)。但是,Resharper 也无法识别这些外部资源名称,导致在我编辑 XAML 时资源名称下出现大量曲线。

我发现我可以通过在每个窗口和用户控件中包含上述 XAML 来修复 VS 设计器和 Resharper,但这会对内存和/或性能产生不利影响吗?每个窗口都会获得一份单独的资源副本吗?

【问题讨论】:

  • 嗯,IDE 和工具中的错误不应该影响您的代码。此外,在每个控件中包含资源字典是一种容易出错的方式(如果您决定重命名字典怎么办?添加另一个?)。
  • 我会尝试在设计模式下添加一个解决问题的怪癖。 (也许这会有所帮助:public class MyUserControlBase : UserControl { public MyUserControlBase() { if (DesignerProperties.GetIsInDesignMode(this)) LoadExternalDictionariesExplicitlyHere(); ...
  • @Vlad 我已经学会了忍受这些曲线——这种修复 Resharper 的方法真的只是“很高兴拥有”。我不认为重命名/添加资源会成为问题 - 在我上面的 XAML 示例中,“Generic.xaml”本身只是合并了该程序集中的其他资源负载,因此添加新资源很容易。我更担心在每个窗口中包含 是否会破坏应用程序(或 VS2010)的内存/性能。
  • 性能不应该是你关心的问题,除非它真的打动你。 (省略了有关过早优化的必要引用。)但是,一个简单的解决方法(例如每个控件的构造函数中的Helpers.LoadDictionariesIfInDesignMode(this))似乎是针对 XAML 中的多行代码的单行代码:)
  • @ControlFlow,我在其他地方看到过这个提示,但它对我不起作用。 MyThemesAssembly 是什么类型的项目(它是一个类库)或 xaml 资源的构建操作(“页面”)会有所不同吗?

标签: wpf resharper


【解决方案1】:

我们的应用程序在使用每个 UserControl/View 中引用的 ResourceDictionaries 时遇到了问题。我不建议这样做。通过使用 SharedResourceDictionaries,我们设法将应用程序的内存占用减少了 300 mb。我看起来您最终会为应用程序中的每个 UserControl 实例化一次 ResourceDictionary。不要仅仅为了修复 VS 设计器而这样做。

【讨论】:

    【解决方案2】:

    尝试使用 VS2012。

    我有一个正在使用的测试项目,我正在从外部程序集合并资源字典,在我的 app.xaml 中有这个:

    <Application x:Class="WpfPackDictionaries.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 StartupUri="MainWindow.xaml">
        <Application.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="pack://application:,,,/WPFCommonLibrary;component/Vectors/Vectors.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    </Application>
    

    然后在我的 mainwindow.xaml 中,我有这个路径拉入样式 ModifiablePathStyle:

    <Window xmlns:Control="clr-namespace:WPF.Common.Control;assembly=WPFCommonLibrary"  x:Class="WpfPackDictionaries.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
    
        <Grid>
            <Path Style="{StaticResource ModifiablePathStyle}" Fill="Red"/>
            <Control:Jabberwocky />
        </Grid>
    </Window>
    

    Intellisense/Resharper (V7.1 10/31 (Early Access Build)) 可以识别样式并且我没有波浪线:

    因此你有没有尝试过在 VS2012 中工作?

    【讨论】:

    • 我们最终将迁移到 VS2012,但仍在等待管理层的 $$$!
    • @AndrewStephens 所有最好的工作都是在尊重管理的情况下完成的。 ;-)
    • @AndrewStephens 为您的 xaml 工作使用 VS2012 Express 版本。它仍然可以编译 .Net 3.5/4.0 项目而无需更改 .prj 或 .sln 项目。
    • @OmegaMan 我在 VS2012 中使用 Resharper 7.1.25.234(官方版本)尝试了完全相同的方法,但我在样式名称下得到了波浪线。我还希望智能感知能够正常工作(这样我就可以开始编写样式的名称,而 ctrl+space 将填充其余部分)。对你有用吗?
    【解决方案3】:

    VS2012 能够“看到”资源,因为 VS XAML 设计器在设计时加载并执行您的代码,因此 VS 可以检查在运行时可用的资源。 ReSharper 从不使用设计时代码执行(因为这要求您的代码始终处于可编译状态),因此 XAML 支持变得更加复杂。

    ReSharper 8.0 实现了对 BAML 反编译的支持,并提取 XAML 文件列表并从引用的二进制程序集中解析 XAML 资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      相关资源
      最近更新 更多