同一个 ResourceDictionary 的多个实例
Multiple instances of the same ResourceDictionary
我发现 this post 关于提高 ResourceDictionaries
在网络上的性能,但问题是它已经很老了(2011 年)。我正在考虑实现类似的东西,但我想知道 Microsoft 是否没有在 .NET Framework 的最新版本中修复此问题。关于这个话题我有几个问题,我希望这里有人能给出答案:
- .NET Framework 4.6.1 是否仍在通过创建它们的多个实例来管理
ResourceDictionaries
,每次将它们分配给一个控件时一个实例?
- 当我在名为
"StylesAssembly"
的 ResourceDictionary
中调用 "ButtonStyles"
的样式 "CustomButtonStyle"
时,这甚至是一个问题,然后在 [=] 中引用一个应用程序的 16=],有 20 个 Buttons
分配给它们 CustomButtonStyle
?
- 我理解的对吗,在上面的例子中,会有20个
"ButtonStyles"
ResourceDictionary
的实例?
Do I understand it correctly, that in the case above, there will be 20 instances of "ButtonStyles" ResourceDictionary
?
没有。只有一个。
Is it even an issue when I have for example style "CustomButtonStyle" in my ResourceDictionary
called "ButtonStyles" in assembly called "StylesAssembly", which is then referenced in App.xaml
of an application, that has 20 Buttons with CustomButtonStyle assigned to them?
如果您将 ResourceDictionary
合并到 App.xaml
中并在应用程序的视图中创建 20 个 Button
元素,那么 [=10= 仍然只有一个实例] class 已创建。
您可以通过在 ResourceDictionary
中添加代码隐藏 class 来自行确认:
Is it possible to set code behind a resource dictionary in WPF for event handling?
...并在构造函数中放置一个断点。
创建的 ResourceDictionary
中定义的 Style
也只有一个实例。
感谢@mm8 post回答你的问题。 100% 正确,我只想 post 我自己的答案,因为我发现了一些有趣的东西,可能对其他人有用。
答案是:如果在应用程序中引用 ResourceDictionary 实例将只创建一次(无论许多控件使用其样式),但每次在另一个应用程序中引用它时都会再次实例化应用程序中也使用的 ResourceDictionary。
所以为了给你这个案例的例子,假设我们有以下结构:
- StylesAssembly.dll
- ButtonResourceDictionary.xaml
- CustomButtonResourceDictionary.xaml
- Application.exe
- App.xaml
- MainWindow.xaml
ButtonResourceDictionary.xaml 有以下代码:
<Style x:Key="DefaultButtonStyle" TargetType="{x:Type Button}">
<!-- Some setters -->
</Style>
CustomButtonResourceDictionary.xaml 有以下代码,它使用 ButtonResourceDictionary.xaml
:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource DefaultButtonStyle}">
<!-- Some setters -->
</Style>
Application.exe
引用了 StylesAssembly.dll
并且 App.xaml 中有以下代码:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/StylesAssembly;component/ButtonResourceDictionary.xaml" />
<ResourceDictionary Source="pack://application:,,,/StylesAssembly;component/CustomButtonResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
现在如果我们的MainWindow.xaml里面有类似的东西,ButtonResourceDictionary.xaml
将只有一个实例:
<StackPanel>
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
</StackPanel>
但是如果我们的MainWindow.xaml里面有这样的东西,CustomButtonResourceDictionary.xaml
会有一个实例,但是ButtonResourceDictionary.xaml
会有两个实例:
<StackPanel>
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
</StackPanel>
这是因为前两个 Buttons
使用来自 ButtonResourceDictionary.xaml
的样式 DefaultButtonStyle
,但另外三个 Buttons
使用来自 [=20] 的样式 CustomButtonStyle
=],它在其代码中合并了 ButtonResourceDictionary.xaml
。
我最近一直在和朋友一起研究替代解决方案,我想分享一下。目标是能够在任何地方使用 ResourceDictionaries 并以任何必要的方式合并它们,但仍然只实例化一次并且不会破坏 VS 设计器和 Blend 等。
说明:
1. 根据需要在 xaml 中使用合并的 ResourceDictionaries。
2.参考nuget包Sundew.Xaml.Optimizations and Sundew.Xaml.Optimizer
3. 在项目的根目录中添加一个 sxo-settings.json 并启用 ResourceDictionaryCachingOptimizer
4. 建造
构建将使用 caching/shared ResourceDictionary,但设计人员也会工作,因为他们只看到普通的 ResourceDictionary。
有关详细信息,请参阅:https://github.com/hugener/Sundew.Xaml.Optimizations
和一个样本:https://github.com/hugener/Sundew.Xaml.Optimizer.Sample
我发现 this post 关于提高 ResourceDictionaries
在网络上的性能,但问题是它已经很老了(2011 年)。我正在考虑实现类似的东西,但我想知道 Microsoft 是否没有在 .NET Framework 的最新版本中修复此问题。关于这个话题我有几个问题,我希望这里有人能给出答案:
- .NET Framework 4.6.1 是否仍在通过创建它们的多个实例来管理
ResourceDictionaries
,每次将它们分配给一个控件时一个实例? - 当我在名为
"StylesAssembly"
的ResourceDictionary
中调用"ButtonStyles"
的样式"CustomButtonStyle"
时,这甚至是一个问题,然后在 [=] 中引用一个应用程序的 16=],有 20 个Buttons
分配给它们CustomButtonStyle
? - 我理解的对吗,在上面的例子中,会有20个
"ButtonStyles"
ResourceDictionary
的实例?
Do I understand it correctly, that in the case above, there will be 20 instances of "ButtonStyles"
ResourceDictionary
?
没有。只有一个。
Is it even an issue when I have for example style "CustomButtonStyle" in my
ResourceDictionary
called "ButtonStyles" in assembly called "StylesAssembly", which is then referenced inApp.xaml
of an application, that has 20 Buttons with CustomButtonStyle assigned to them?
如果您将 ResourceDictionary
合并到 App.xaml
中并在应用程序的视图中创建 20 个 Button
元素,那么 [=10= 仍然只有一个实例] class 已创建。
您可以通过在 ResourceDictionary
中添加代码隐藏 class 来自行确认:
Is it possible to set code behind a resource dictionary in WPF for event handling?
...并在构造函数中放置一个断点。
创建的 ResourceDictionary
中定义的 Style
也只有一个实例。
感谢@mm8 post回答你的问题。 100% 正确,我只想 post 我自己的答案,因为我发现了一些有趣的东西,可能对其他人有用。
答案是:如果在应用程序中引用 ResourceDictionary 实例将只创建一次(无论许多控件使用其样式),但每次在另一个应用程序中引用它时都会再次实例化应用程序中也使用的 ResourceDictionary。
所以为了给你这个案例的例子,假设我们有以下结构:
- StylesAssembly.dll
- ButtonResourceDictionary.xaml
- CustomButtonResourceDictionary.xaml
- Application.exe
- App.xaml
- MainWindow.xaml
ButtonResourceDictionary.xaml 有以下代码:
<Style x:Key="DefaultButtonStyle" TargetType="{x:Type Button}">
<!-- Some setters -->
</Style>
CustomButtonResourceDictionary.xaml 有以下代码,它使用 ButtonResourceDictionary.xaml
:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ButtonResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="CustomButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource DefaultButtonStyle}">
<!-- Some setters -->
</Style>
Application.exe
引用了 StylesAssembly.dll
并且 App.xaml 中有以下代码:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/StylesAssembly;component/ButtonResourceDictionary.xaml" />
<ResourceDictionary Source="pack://application:,,,/StylesAssembly;component/CustomButtonResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
现在如果我们的MainWindow.xaml里面有类似的东西,ButtonResourceDictionary.xaml
将只有一个实例:
<StackPanel>
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
</StackPanel>
但是如果我们的MainWindow.xaml里面有这样的东西,CustomButtonResourceDictionary.xaml
会有一个实例,但是ButtonResourceDictionary.xaml
会有两个实例:
<StackPanel>
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource DefaultButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
<Button Style="{StaticResource CustomButtonStyle}" />
</StackPanel>
这是因为前两个 Buttons
使用来自 ButtonResourceDictionary.xaml
的样式 DefaultButtonStyle
,但另外三个 Buttons
使用来自 [=20] 的样式 CustomButtonStyle
=],它在其代码中合并了 ButtonResourceDictionary.xaml
。
我最近一直在和朋友一起研究替代解决方案,我想分享一下。目标是能够在任何地方使用 ResourceDictionaries 并以任何必要的方式合并它们,但仍然只实例化一次并且不会破坏 VS 设计器和 Blend 等。
说明:
1. 根据需要在 xaml 中使用合并的 ResourceDictionaries。
2.参考nuget包Sundew.Xaml.Optimizations and Sundew.Xaml.Optimizer
3. 在项目的根目录中添加一个 sxo-settings.json 并启用 ResourceDictionaryCachingOptimizer
4. 建造
构建将使用 caching/shared ResourceDictionary,但设计人员也会工作,因为他们只看到普通的 ResourceDictionary。
有关详细信息,请参阅:https://github.com/hugener/Sundew.Xaml.Optimizations
和一个样本:https://github.com/hugener/Sundew.Xaml.Optimizer.Sample