He encontrado esta publicación sobre la mejora del rendimiento de ResourceDictionaries en la web, pero el problema es que es bastante viejo (2011). Estaba pensando en implementar algo como esto, pero me pregunto si Microsoft no ha solucionado esto en las últimas versiones de .NET Framework. Tengo algunas preguntas sobre este tema, que espero que alguien aquí pueda responder a:

  1. ¿.NET Framework 4.6.1 todavía administra ResourceDictionaries al hacer varias instancias de ellas, una por cada vez que se asignan a un control?
  2. ¿Es incluso un problema cuando tengo, por ejemplo, el estilo "CustomButtonStyle" en mi ResourceDictionary llamado "ButtonStyles" en el conjunto llamado "StylesAssembly", que luego se hace referencia en App.xaml de un aplicación, que tiene 20 Buttons con CustomButtonStyle asignado a ellos?
  3. ¿Lo entiendo correctamente, en el caso anterior, habrá 20 instancias de "ButtonStyles" ResourceDictionary?
4
Kacper Stachowski 18 oct. 2017 a las 14:01

3 respuestas

La mejor respuesta

Gracias @ mm8 por publicar tu respuesta. Es 100% correcto, solo quiero publicar mi propia respuesta, porque descubrí algo interesante, que puede ser útil para otra persona.

La respuesta es: La instancia de ResourceDictionary se creará solo una vez si se hace referencia en la aplicación (sin importar que muchos controles usen sus estilos), PERO se instanciará nuevamente cada vez que se haga referencia en otra ResourceDictionary que también se usa en aplicación.


Entonces, para darle un ejemplo de este caso, supongamos que tenemos la siguiente estructura:

- StylesAssembly.dll
  - ButtonResourceDictionary.xaml
  - CustomButtonResourceDictionary.xaml

- Application.exe
  - App.xaml
  - MainWindow.xaml

ButtonResourceDictionary.xaml tiene el siguiente código:

<Style x:Key="DefaultButtonStyle" TargetType="{x:Type Button}">
    <!-- Some setters -->
</Style>

CustomButtonResourceDictionary.xaml tiene el siguiente código, que utiliza 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 tiene una referencia a StylesAssembly.dll y hay un código siguiente en la 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>

Ahora, si nuestro MainWindow.xaml tiene algo como esto, ButtonResourceDictionary.xaml solo tendrá una instancia :

<StackPanel>
    <Button Style="{StaticResource DefaultButtonStyle}" />
    <Button Style="{StaticResource DefaultButtonStyle}" />
    <Button Style="{StaticResource DefaultButtonStyle}" />
    <Button Style="{StaticResource DefaultButtonStyle}" />
    <Button Style="{StaticResource DefaultButtonStyle}" />
</StackPanel>

Pero si nuestro MainWindow.xaml tiene algo como esto, CustomButtonResourceDictionary.xaml tendrá una instancia, pero ButtonResourceDictionary.xaml tendrá dos instancias :

<StackPanel>
    <Button Style="{StaticResource DefaultButtonStyle}" />
    <Button Style="{StaticResource DefaultButtonStyle}" />
    <Button Style="{StaticResource CustomButtonStyle}" />
    <Button Style="{StaticResource CustomButtonStyle}" />
    <Button Style="{StaticResource CustomButtonStyle}" />
</StackPanel>

Ocurre porque los dos primeros Buttons usan el estilo DefaultButtonStyle de ButtonResourceDictionary.xaml, pero otros tres Buttons usan el estilo CustomButtonStyle que viene de CustomButtonResourceDictionary.xaml, que se fusiona ButtonResourceDictionary.xaml en su código.

3
Kacper Stachowski 18 oct. 2017 a las 13:50

¿Lo entiendo correctamente, en el caso anterior, habrá 20 instancias de "ButtonStyles" ResourceDictionary?

No solo uno.

¿Es incluso un problema cuando tengo, por ejemplo, el estilo "CustomButtonStyle" en mi ResourceDictionary llamado "ButtonStyles" en el ensamblaje llamado "StylesAssembly", que luego se hace referencia en App.xaml de una aplicación, que tiene 20 botones con CustomButtonStyle asignado a ellos?

Si combina ResourceDictionary en su App.xaml y crea 20 elementos Button en las vistas de su aplicación, seguirá habiendo una sola instancia de la clase ResourceDictionary creada.

Puede confirmarlo usted mismo agregando una clase de código subyacente a ResourceDictionary:

¿Es posible establecer código detrás de un diccionario de recursos en WPF para el manejo de eventos?

... Y poner un punto de interrupción en la constructora.

También habrá una sola instancia del Style definido en el ResourceDictionary creado.

2
mm8 18 oct. 2017 a las 12:45

Recientemente he estado trabajando en una solución alternativa con un amigo y quería compartirla. El objetivo es poder usar ResourceDictionaries en cualquier lugar y fusionarlos de la manera que sea necesaria, pero aún así tenerlos instanciados solo una vez y sin romper el diseñador VS y Blend, etc.

Instrucciones:
1. Utilice los diccionarios de recursos combinados en xaml como mejor le parezca.
2. Paquetes nuget de referencia Sundew.Xaml.Optimizations y Sundew.Xaml.Optimizer
3. Agregue un sxo-settings.json en la raíz de su proyecto y habilite ResourceDictionaryCachingOptimizer
4. Construir
La compilación usará un ResourceDictionary de almacenamiento en caché / compartido, pero el diseñador también funcionará porque solo ven el ResourceDictionary normal.

Para obtener más detalles, consulte: https://github.com/hugener/Sundew.Xaml.Optimizations
Y una muestra: https://github.com/hugener/Sundew.Xaml.Optimizer. Muestra

1
Hugge 14 abr. 2019 a las 20:58