none
ResourceDictionary RRS feed

  • Pregunta

  • Hola.

    Estoy de lleno con el diseño de estilos y utilizo varios ResourceDictionary, pero a la hora de aplicarlos solamente copia el estilo de el último que se ha introducido --> Segundo.xaml

     

     

    <ResourceDictionary>
          <ResourceDictionary.MergedDictionaries>
               <ResourceDictionary source="primero.xaml"/>
    	   <ResourceDictionary source="segundo.xaml"/>			
          </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
    

     

     

    ¿Como prodría introducir diferentes objetos y especificarle con que estilo quiero que lo haga?.

    He estado mirando por google para buscar la solución pero no he encontrado nada.

     

    Un saludo


    • Editado makinavaja domingo, 27 de noviembre de 2011 14:54
    domingo, 27 de noviembre de 2011 14:53

Respuestas

  • Hola makinavaja.

    1.- Si, segun he puesto yo el ejemplo me baso en el uso de union de diccionarios por si tienes mas de un diccionario que forme un tema en lugar de tener todos los estilos en un unico archivo, de modo que en el archivo app.xaml debes declararlo asi:

        <Application.Resources>
            
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <!-- Recursos iniciales -->
                    <ResourceDictionary Source="Recursos\ResourceDictionary1.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
            
        </Application.Resources>
    

    Incluyendo los recursos en en tag mergedDictionaries para hacer unir todos los archivos que pongas dentro.

    2.- segun he visto tus estilos, en el caso de los botones, los asignas a todos los botones sin clave, de modo que no hace falta que pongas nada en el tag 'Style' lo puedes quitar, esto solo es por si creas varios estilos para un boton y quieres asignar uno especifico a cada boton.

    3.- a la funcion 'getResourceDictionary' se le debe pasar la ruta de tus recursos, si los tienes en una unica carpeta y usas un unico archivo para todos los recursos puedes modificar las funciones para simplificarlas, pero en cualquier caso, asegurate de que en esta funcion :

            private static ResourceDictionary getResourceDictionary(string _path)
            {
                // recorrer los recursos para obtener el recurso deseado
                foreach (ResourceDictionary res in Application.Current.Resources.MergedDictionaries)
                {
                    if (res.Source != null)
                    {
                        string source = res.Source.ToString();
                        if (source.Contains(_path))
                        {
                            return res;
                        }
                    }
                }
                return null;
            }
    

    En la linea 'source.Contains(_path) debe de coincidir el path que le pasas al que obtiene ya que es posible que la barra del directorio se invierta '/' o '\' y eso hace que no se borre el recurso, pero funcionaria igual, aunque no se borrarian y se irian añadiendo muchos recursos (asegurate de que esto no ocurre)

    Yo he puesto un ejemplo adaptado y sencillo, pero deberias de modificar las funciones para asegurarte de que hacen lo que quieres, (eliminar los recursos anteriores y añadir los nuevos).

    Para tu caso concreto, es mucho mas sencillo dejar el codigo asi:

            public static void ChangeResource(Uri _resourceUri)
            {
                ResourceDictionary rd = new ResourceDictionary();
                rd.Source = _resourceUri;
    
                // eliminar todos los recursos
                Application.Current.Resources.MergedDictionaries.Clear();
                // añadir los nuevos recursos
                Application.Current.Resources.MergedDictionaries.Add(rd);
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Button btn = (Button)sender;
    
                switch (btn.Name)
                {
                    // cambiar a los recursos 'ResourceDictionary1.xaml'
                    case "btnStyle1":
                        ChangeResource(new Uri("Recursos/ResourceDictionary1.xaml", UriKind.Relative));
                        break;
    
                    // cambiar a los recursos 'ResourceDictionary2.xaml'
                    case "btnStyle2":
                        ChangeResource(new Uri("Recursos/ResourceDictionary2.xaml", UriKind.Relative));
                        break;
                }
            }
    

    La forma que he planteado inicialmente es para dar mayor flexibilidad en el uso de varios archivos de recursos para un mismo tema, pero esta ultima forma sirve para una gran mayoria de casos.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta makinavaja jueves, 1 de diciembre de 2011 23:57
    jueves, 1 de diciembre de 2011 13:42

Todas las respuestas

  • hola makinavaja.

    no puedes tener dos recursos con claves iguales ya que tiene un comportamiento inesperado, si quieres tener por ejemplo 2 temas, debes eliminar uno antes de asignar el segundo, en este post, comento lo que suelo hacer:

    http://social.msdn.microsoft.com/Forums/es/wpfes/thread/3fc0ac6a-a2de-4d8b-8e58-a48c9ba00eba

    basicamente son unas funciones para buscar, eliminar y añadir un recurso, de modo que se pueda cambiar de tema facilmente.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    martes, 29 de noviembre de 2011 12:33
  • Gracias por la respuesta David.

    ¿Tienes algún ejemplo creado? Es que no consigo hacerlo con la versión Express.

    Un saludo

    miércoles, 30 de noviembre de 2011 23:27
  • Saludos Makinavaja, deberias tener algo asi:

    <ResourceDictionary
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:System="clr-namespace:System;assembly=mscorlib"
      xmlns: .....!!>
    
        <!--  estilo boton logout  -->
        <Style x:Key="LogoutButtonStyle" TargetType="HyperlinkButton">
            <Setter Property="FontSize" Value="11"/>
            <.....!! />
        </Style>
    
        <Style x:Key="SpacerStyle" TargetType="TextBlock">
            <Setter Property="FontSize" Value="11"/>
            <Setter ......!!/>
         </Style>
    
         <Style x:Key="IDENTIFICADORUNICO" TargetType="....!!>
               <Setter .....!!>
         </Style>
    
          .....
          
    </ResourceDictionary>

     En negrilla los identificadores que deben ser unicos en cada estilo definido.


    MCPD: Enterprise Applications Developer | MCTS: Sql Server 2005

    • Editado omedsaenz jueves, 1 de diciembre de 2011 1:37
    jueves, 1 de diciembre de 2011 1:34
  • Hola. Gracias por responder.

     

    Si, solamente tiene que haber un identificador por control.

    Creo un ResourceDictionary (*.xaml) con los estilos de todos los controles pero no quiero que mi proyecto

    se limite solamente a un estilo y creo otro ResourceDictionary (*.xaml) con otros estilos de todos los controles.

    Después agregas los 2 ResourceDictionary (*.xaml) al proyecto y los identifica <ResourceDictionary.MergedDictionaries>.

    Como puedo especificarle, cuando agrege algún control, con que ResourceDictionary quiero trabajar de los 2 que he

    incluido en el proyecto.

     

    David Gonzalez, creo que está diciendo que puedes indicarle con que ResourceDictionary quieres trabajar

    pero no puedo/no se hacer lo que dice.

     

    Un saludo y gracias

    jueves, 1 de diciembre de 2011 3:14
  • Hola makinavaja

    te pongo un ejmplillo:

     

    creamos 2 archivos de recursos dentro del directorio 'recursos' por ejemplo

    Luego en el archivo app.xaml se define el que se queda por defecto:

        <Application.Resources>
             
        	<ResourceDictionary>
        		<ResourceDictionary.MergedDictionaries>
                    
                    <!-- Recursos iniciales -->
        			<ResourceDictionary Source="Recursos\ResourceDictionary1.xaml"/>
                    
        		</ResourceDictionary.MergedDictionaries>
             
             
        	</ResourceDictionary>
             
        </Application.Resources>
    

    Como ejemplo ponemos en un archivo .xaml 2 botones para cambiar los recursos:

        <Grid x:Name="mainGrid">
            
        	<Button Content="cambiar estilo1" Name="btnStyle1" HorizontalAlignment="Left" Height="40" Margin="113,91,0,0" VerticalAlignment="Top" 
                    Width="91" Style="{DynamicResource ButtonStyle1}" Click="Button_Click" />
            <Button Content="cambiar estilo2" Name="btnStyle2" HorizontalAlignment="Left" Height="40" Margin="320,91,0,0" VerticalAlignment="Top" 
                    Width="91" Style="{DynamicResource ButtonStyle1}" Click="Button_Click" />
    
        </Grid>
    

    y en el codigo definimos el evento que cambiara los recursos:

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Button btn = (Button)sender;
    
                switch (btn.Name)
                {
                    // cambiar a los recursos 'ResourceDictionary1.xaml'
                    case "btnStyle1":
                        ChangeResource(new Uri("Recursos/ResourceDictionary1.xaml", UriKind.Relative));
                        break;
    
                    // cambiar a los recursos 'ResourceDictionary2.xaml'
                    case "btnStyle2":
                        ChangeResource(new Uri("Recursos/ResourceDictionary2.xaml", UriKind.Relative));
                        break;
                }
            }
    
    
            /// <summary>
            /// Funcion para cambiar un recurso en la aplicacion
            /// </summary>
            /// <param name="_resourceUri"></param>
            public static void ChangeResource(Uri _resourceUri)
            {
                ResourceDictionary rd = new ResourceDictionary();
                rd.Source = _resourceUri;
    
                // buscar y eliminar los recursos actuales
                ResetResources();
    
                // añadir los nuevos recursos
                Application.Current.Resources.MergedDictionaries.Add(rd);
            }
    
            public static void ResetResources()
            {
                // obtener el recurso a eliminar
                ResourceDictionary res = getResourceDictionary("Recursos\\");
                if (res != null)
                    Application.Current.Resources.MergedDictionaries.Remove(res);
            }
    
            private static ResourceDictionary getResourceDictionary(string _path)
            {
                // recorrer los recursos para obtener el recurso deseado
                foreach (ResourceDictionary res in Application.Current.Resources.MergedDictionaries)
                {
                    if (res.Source != null)
                    {
                        string source = res.Source.ToString();
                        if (source.Contains(_path))
                        {
                            return res;
                        }
                    }
                }
                return null;
            }
    

    y ya esta.

    Cuando se pulse uno u otro boton se eliminaran los recursos actuales y se insertaran los del nuevo resourceDictionary.

    Esto es un ejemplo basico, en el que se eliminan todos los recursos para poner los nuevos, si quieres otra cosa lo tienes que modificar a tu gusto.

    Si tienes algun problema comentalo.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    jueves, 1 de diciembre de 2011 9:07
  • Gracias David por la respuesta.

     

     

    <Button Content="cambiar estilo1" Name="btnStyle1" HorizontalAlignment="Left" Height="40" Margin="113,91,0,0" VerticalAlignment="Top" 
                    Width="91" Style="{DynamicResource ButtonStyle1}" Click="Button_Click" />


    En DynamicResource no se que poner por ButtonStyle1.



    Cuelgo el ejemplo para que lo veas.
    http://uppit.com/2i548ebjx8f9/ejemploWPF.rar




    Un saludo y gracias

     

    jueves, 1 de diciembre de 2011 11:46
  • Hola makinavaja.

    1.- Si, segun he puesto yo el ejemplo me baso en el uso de union de diccionarios por si tienes mas de un diccionario que forme un tema en lugar de tener todos los estilos en un unico archivo, de modo que en el archivo app.xaml debes declararlo asi:

        <Application.Resources>
            
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <!-- Recursos iniciales -->
                    <ResourceDictionary Source="Recursos\ResourceDictionary1.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
            
        </Application.Resources>
    

    Incluyendo los recursos en en tag mergedDictionaries para hacer unir todos los archivos que pongas dentro.

    2.- segun he visto tus estilos, en el caso de los botones, los asignas a todos los botones sin clave, de modo que no hace falta que pongas nada en el tag 'Style' lo puedes quitar, esto solo es por si creas varios estilos para un boton y quieres asignar uno especifico a cada boton.

    3.- a la funcion 'getResourceDictionary' se le debe pasar la ruta de tus recursos, si los tienes en una unica carpeta y usas un unico archivo para todos los recursos puedes modificar las funciones para simplificarlas, pero en cualquier caso, asegurate de que en esta funcion :

            private static ResourceDictionary getResourceDictionary(string _path)
            {
                // recorrer los recursos para obtener el recurso deseado
                foreach (ResourceDictionary res in Application.Current.Resources.MergedDictionaries)
                {
                    if (res.Source != null)
                    {
                        string source = res.Source.ToString();
                        if (source.Contains(_path))
                        {
                            return res;
                        }
                    }
                }
                return null;
            }
    

    En la linea 'source.Contains(_path) debe de coincidir el path que le pasas al que obtiene ya que es posible que la barra del directorio se invierta '/' o '\' y eso hace que no se borre el recurso, pero funcionaria igual, aunque no se borrarian y se irian añadiendo muchos recursos (asegurate de que esto no ocurre)

    Yo he puesto un ejemplo adaptado y sencillo, pero deberias de modificar las funciones para asegurarte de que hacen lo que quieres, (eliminar los recursos anteriores y añadir los nuevos).

    Para tu caso concreto, es mucho mas sencillo dejar el codigo asi:

            public static void ChangeResource(Uri _resourceUri)
            {
                ResourceDictionary rd = new ResourceDictionary();
                rd.Source = _resourceUri;
    
                // eliminar todos los recursos
                Application.Current.Resources.MergedDictionaries.Clear();
                // añadir los nuevos recursos
                Application.Current.Resources.MergedDictionaries.Add(rd);
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Button btn = (Button)sender;
    
                switch (btn.Name)
                {
                    // cambiar a los recursos 'ResourceDictionary1.xaml'
                    case "btnStyle1":
                        ChangeResource(new Uri("Recursos/ResourceDictionary1.xaml", UriKind.Relative));
                        break;
    
                    // cambiar a los recursos 'ResourceDictionary2.xaml'
                    case "btnStyle2":
                        ChangeResource(new Uri("Recursos/ResourceDictionary2.xaml", UriKind.Relative));
                        break;
                }
            }
    

    La forma que he planteado inicialmente es para dar mayor flexibilidad en el uso de varios archivos de recursos para un mismo tema, pero esta ultima forma sirve para una gran mayoria de casos.

     


    Saludos
    David González
    MCP, MCTS
    Visita mi Blog en: http://www.dgzornoza.com/
    • Marcado como respuesta makinavaja jueves, 1 de diciembre de 2011 23:57
    jueves, 1 de diciembre de 2011 13:42