2009-01-10 13 views
58

Estoy tratando de establecer el estilo predeterminado para cada ventana en mi aplicación Windows WPF en mi app.xaml. Hasta ahora tengo esto en App.xaml:Cómo configurar el estilo de ventana WPF predeterminado en app.xaml?

<Application.Resources> 
    <ResourceDictionary> 
     <Style x:Key="WindowStyle" TargetType="{x:Type Window}"> 
      <Setter Property="Background" Value="Blue" /> 
     </Style> 
    </ResourceDictionary> 
</Application.Resources> 

yo puede conseguir a la ventana que aparezca con este estilo cuando se ejecuta la aplicación (pero no se VS diseñador) diciéndoles específicamente la ventana para utilizar este estilo a través de:

Style="{DynamicResource WindowStyle} 

Esto funciona, pero no es ideal. Entonces, ¿cómo puedo:

  1. ¿Todas las ventanas usan automáticamente el estilo (así que no tengo que especificarlo en cada ventana)?
  2. ¿El diseñador VS muestra el estilo?

¡Gracias!

Respuesta

8

El diseñador no funciona porque está especificando un DynamicResource. Cambie esto a StaticResource y todo estará bien.

Para aplicar a todas las ventanas, debe quitar la clave x: del estilo. Establecer TargetType establece implícitamente la x: Key a lo que está en TargetType. Sin embargo, en mis pruebas, esto no funciona, entonces lo estoy investigando.

Si configuro TargetType en x: escriba TextBlock, el diseñador funciona perfectamente, simplemente parece ser la ventana que muestra un comportamiento diferente.

+1

Sí, me encontré con el mismo problema. Gishu dijo anteriormente que parece que el estilo implícito para Windows no se aplicará a su ventana, ya que en realidad es una clase derivada. –

45

Para añadir a lo que dice Ray:

para los estilos, ya sea que usted necesita para suministrar una clave/o especificar un ID TargetType.

Si un FrameworkElement no tiene un especifica explícitamente estilo, se siempre buscar un recurso de estilo, utilizando su propio tipo como la clave
- Programación de WPF (Sells, Griffith)

Si proporciona un TargetType, todas las instancias de ese tipo tendrán el estilo aplicado. Sin embargo, los tipos derivados no ... parece. <Style TargetType="{x:Type Window}"> no funcionará para todas sus derivaciones/ventanas personalizadas. <Style TargetType="{x:Type local:MyWindow}"> se aplicará solo a MyWindow. Por lo que las opciones son

  • utilizar un estilo de llave que especifique como la propiedad de estilo de cada ventana que desea aplicar el estilo. El diseñador mostrará la ventana con estilo.

.

<Application.Resources> 
     <Style x:Key="MyWindowStyle"> 
      <Setter Property="Control.Background" Value="PaleGreen"/> 
      <Setter Property="Window.Title" Value="Styled Window"/> 
     </Style> 
    </Application.Resources> ... 
    <Window x:Class="MyNS.MyWindow" Style="{StaticResource MyWindowStyleKey}"> ... 
  • O bien, podría derivar de una clase BaseWindow personalizado (que tiene its own quirks), donde se define la propiedad de estilo durante la inicialización etapa Ctor// Cargar una vez. Todas las Derivaciones tendrían automáticamente el estilo aplicado. Pero el diseñador no se dará cuenta de su estilo. Debe ejecutar su aplicación para ver el estilo que se está aplicando.Supongo que el diseñador solo ejecuta InitializeComponent (que es un código generado automáticamente/por el diseñador) por lo que se aplica XAML pero no código de código personalizado.

Así que diría que los estilos explícitamente especificados son lo menos trabajo. De todos modos, puedes cambiar los aspectos del Estilo centralmente.

+2

La última línea " Anthony

+0

Puede 'cascadear' estilo usando la propiedad BasedOn. 'BasedOn =" {StaticResource {x: Type Window}} "' Sin embargo, no he podido hacer que Window acepte los estilos sin clave.Supongo que es porque no reconocen los tipos derivados, como dijiste. –

+0

Su código está lleno de errores y ni siquiera se acerca a la compilación y es efectivamente inútil, por ejemplo, usando 'MyWindowStyleKey' y' MyWindowStyle'. Una de las muchas razones por las cuales casi 9 años después no ha sido aceptado. – Matt

18

sabe que esto es años más tarde, pero ya que la cuestión está todavía aquí ...

  1. crear un diccionario de recursos en su proyecto (Haga clic derecho en el proyecto ...)

    I 'll crear una nueva carpeta en el proyecto denominado "Activos" y "put resourceDict.XAML en ella

  2. añadir el código a resourceDict.XAML:.

    <Style x:Key="WindowStyle" Target Type="Window" > 
        <Setter Property="Background" Value="Blue" /> 
    </Style> 
    
  3. En su archivo XAML Proyecto añadir lo siguiente en la ventana:

    <Window.Resources> 
        <ResourceDictionary> 
         <!-- Believe it or not the next line fixes a bug MS acknowledges --> 
         <Style TargetType="{x:Type Rectangle}" /> 
         <ResourceDictionary.MergedDictionaries> 
          <ResourceDictionary Source="/Assets/resourceDict.XAML" /> 
         </ResourceDictionary.MergedDictionaries> 
        <ResourceDictionary> 
    </Window.Resources> 
    

    ref el siguiente sitio web: Trouble referencing a Resource Dictionary that contains a Merged Dictionary "Hay un error: si todos los estilos por defecto se anidan en los diccionarios fusionadas tres niveles de profundidad (o más) el diccionario superior no se marca, por lo que la búsqueda se salta. El trabajo alternativo consiste en poner un Estilo predeterminado a algo, cualquier cosa, en el diccionario raíz. " Y parece arreglar las cosas de manera confiable. Ir a la figura ...

  4. Y finalmente, en Ventana, tal vez después del Título, pero antes de la última ventana '>':.

    Style="{DynamicResource windowStyle}" 
    
  5. Y usted tendrá que añadir el código en los pasos 3 4 & a cada proyecto en el que desea aplicar el estilo a

  6. Si quería para usar un fondo degradado en lugar de un color sólido, agregue el siguiente bacalao e para el resourceDict.XAML:

    <LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0" 
         EndPoint="0,1" > 
    <GradientStop Color= "AliceBlue" Offset="0" /> 
    <GradientStop Color= "Blue" Offset=".75" /> 
    </LinearGradientBrush> 
    
  7. y modificar su estilo Setter para el color de fondo para leer:

    <Setter Property="Background" Value="{DynamicResource 
         windowGradientBackground}" /> 
    

Pasos 3 4 & ser necesario repetir en cada project.XAML archivo como se describió anteriormente, pero bueno, ¡obtienes Windows uniforme a través de la Solución! Y el mismo proceso podría aplicarse a cualquier control que desee tener un aspecto uniforme, botones, lo que sea.

Para cualquier persona que llegue tan tarde, espero que esto ayude, ya que estoy seguro de que los carteles originales lo solucionaron hace años.

Paul

+0

El consejo aquí sobre no insertar MergedDictionaries dentro de MergedDictionaries fue la solución para mí. Simplemente declare todos los archivos de temas directamente desde App.xaml ¡Así que gracias! –

1

Para aquellos que luchan con esto una solución al problema: ¿Cómo puedo tener un estilo personalizado puede aplicar a todos mis automtically Tipos de ventana derivada? A continuación se muestra la solución que se me ocurrió

NOTA: Realmente no quería derivarme del tipo Ventana o tengo que insertar XAML en cada ventana para forzar una actualización de estilo, etc.por razones específicas de mi proyecto (los consumidores de mi producto usamos nuestra biblioteca genérica de estilo reutilizable y creamos su propio diseño/ventanas, etc.), así que realmente estaba motivado para encontrar una solución que funcionase que estaba dispuesto a vivir con cualquier lado efectos

Necesitar iterar a través de todas las ventanas instanciadas y simplemente forzarlas a usar el nuevo estilo personalizado que ha definido para el tipo de Ventana. Esto funciona muy bien para las ventanas que ya están abiertas, pero cuando se crea una instancia de una ventana o una ventana secundaria, no sabrá usar el tipo nuevo/personalizado que se ha declarado para su tipo base; el tipo de ventana vainilla. Así que lo mejor que se me ocurrió fue utilizar LostKeyBoardFocus en MainWindow para cuando pierde Focus to a ChildWindow (IOW cuando se ha creado una ventana hija) y luego invocar este FixupWindowDerivedTypes().

Si alguien tiene una mejor solución para "detectar" cuando cualquier tipo de tipo derivado de la ventana se crea una instancia y, por lo tanto, llama a los FixupWindowDerivedTypes() que sería genial. Puede haber algo útil al manejar WM_WINDOWPOSCHANGING en esta área también.

De modo que esta solución no es elegante por decir, pero hace el trabajo sin tener que tocar ningún código o XAML relacionado con mis ventanas.

public static void FixupWindowDerivedTypes() 
    { 
     foreach (Window window in Application.Current.Windows) 
     { 
      //May look strange but kindly inform each of your window derived types to actually use the default style for the window type 

        window.SetResourceReference(FrameworkElement.StyleProperty, DefaultStyleKeyRetriever.GetDefaultStyleKey(window)); 
       } 
      } 
     } 
    } 


//Great little post here from Jafa to retrieve a protected property like DefaultStyleKey without using reflection. 
http://themechanicalbride.blogspot.com/2008/11/protected-dependency-properties-are-not.html 

//Helper class to retrieve a protected property so we can set it 
internal class DefaultStyleKeyRetriever : Control 
{ 
    /// <summary> 
    /// This method retrieves the default style key of a control. 
    /// </summary> 
    /// <param name="control">The control to retrieve the default style key 
    /// from.</param> 
    /// <returns>The default style key of the control.</returns> 
    public static object GetDefaultStyleKey(Control control) 
    { 
     return control.GetValue(Control.DefaultStyleKeyProperty); 
    } 
} 
-1
  1. se ahorrará todos los estilos en un solo archivo XAML (ejemplo design.xaml)

  2. y luego llamar a eso (design.xaml) archivo XAML en todas las páginas como esta manera

igual:

<ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="Design.xaml"/>     
</ResourceDictionary.MergedDictionaries> 
0

Teniendo en cuenta La respuesta de Gishu Descubrí una solución más. Pero podría ser un poco extraño. Si usa el patrón MVVM, puede eliminar el código subyacente de su ventana y el marcado x: Class en el archivo XAML. Por lo tanto, obtendrá una instancia de ventana o su ventana personalizada pero no una instancia de la clase 'MainWindow' derivada de la clase 'Ventana' y marcada como parcial. Estoy creando una ventana similar a VS, así que tuve que heredar la clase de ventana y ampliar su funcionalidad. En ese caso, será posible crear una nueva clase de ventana como parcial que nos permita hacer código subyacente sin herencia.

2

que investigaron este por algunos días y lo hizo trabajar a través del constructor de mi clase de ventana personalizado:

public class KWindow : Window 
{ 
     public KWindow() 
     { 
      this.SetResourceReference(StyleProperty, typeof(KWindow)); 
     } 

     static KWindow() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(KWindow), new FrameworkPropertyMetadata(typeof(KWindow))); 

     } 

     public override void OnApplyTemplate() 
     { 
      base.OnApplyTemplate(); 

      // gets called finally 
     } 
} 

espero que ayude a alguien

1

Puede agregar este código a su App.xaml Cs archivo:

 FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata 
     { 
      DefaultValue = Application.Current.FindResource(typeof(Window)) 
     }); 

Después de esto, el estilo aplicado al tipo Window también se aplicará a todos los tipos derivados de Window

+0

Esta es la única solución que funciona para mi clase 'BaseWindow'. ¡Gracias! – pinki

Cuestiones relacionadas