2010-11-25 24 views
5

que desea aplicar el estilo siguiente a todos los controles que se derivan de ButtonBase¿Cómo aplicar un estilo a una clase y sus descendientes?

<Style 
    TargetType="{x:Type ButtonBase}"> 
    <Setter 
     Property="Cursor" 
     Value="Hand" /> 
</Style> 

pero sólo funciona para una clase dada, no para sus descendientes. ¿Cómo lograr lo que pretendo?

Respuesta

4

Esto no funciona porque cuando un elemento no tiene un estilo asignado explícitamente, WPF encuentra su estilo llamando FindResource, utilizando el tipo de elemento como clave. El hecho de que haya creado un estilo cuya clave sea ButtonBase no importa: WPF encuentra el estilo con la clave Button o ToggleButton y lo usa.

Un método de búsqueda basado en la herencia buscaría el estilo usando el tipo de elemento y luego usaría el tipo base si no se encontraba ningún estilo para el tipo de elemento (y seguiría hasta encontrar un estilo o marcar FrameworkElement) . El problema es que solo funciona si no se encuentra una coincidencia, es decir, si no hay un estilo predeterminado para Button, que por supuesto existe.

Hay dos cosas que puede hacer. Una es hacer lo que sugiere Jens, usando la propiedad BasedOn del estilo para implementar su propia jerarquía de estilos. Sin embargo, eso es algo molesto porque tienes que definir un estilo para cada tipo; si no lo hace, se usará el estilo predeterminado de WPF para ese tipo.

Otra forma es usar un StyleSelector que implemente este comportamiento de búsqueda. De esta manera:

public class InheritanceStyleSelector : StyleSelector 
{ 
    public InheritanceStyleSelector() 
    { 
     Styles = new Dictionary<object, Style>(); 
    } 
    public override Style SelectStyle(object item, DependencyObject container) 
    { 
     Type t = item.GetType(); 
     while(true) 
     { 
      if (Styles.ContainsKey(t)) 
      { 
       return Styles[t]; 
      } 
      if (t == typeof(FrameworkElement) || t == typeof(object)) 
      { 
       return null; 
      } 
      t = t.BaseType; 
     } 
    } 

    public Dictionary<object, Style> Styles { get; set; } 
} 

Puede crear una instancia de este, le dan un conjunto de estilos, y luego fijarlo a cualquier ItemsControl:

<Window x:Class="StyleSelectorDemo.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:StyleSelectorDemo="clr-namespace:StyleSelectorDemo" Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <StyleSelectorDemo:InheritanceStyleSelector x:Key="Selector"> 
      <StyleSelectorDemo:InheritanceStyleSelector.Styles> 
       <Style x:Key="{x:Type ButtonBase}"> 
        <Setter Property="ButtonBase.Background" 
          Value="Red" /> 
       </Style> 
       <Style x:Key="{x:Type ToggleButton}"> 
        <Setter Property="ToggleButton.Background" 
          Value="Yellow" /> 
       </Style> 
      </StyleSelectorDemo:InheritanceStyleSelector.Styles> 
     </StyleSelectorDemo:InheritanceStyleSelector> 
    </Window.Resources> 
    <Grid> 
     <ItemsControl ItemContainerStyleSelector="{StaticResource Selector}"> 
      <Button>This is a regular Button</Button> 
      <ToggleButton>This is a ToggleButton.</ToggleButton> 
      <TextBox>This uses WPF's default style.</TextBox> 
     </ItemsControl> 
    </Grid> 
</Window> 
1

Esto de hecho parece ser una limitación del sistema de estilo.

Enfrentado con este problema, he declarado un estilo de base, y "sub-estilo" esto para cada descendiente que me haya importado.

<Style x:Key="ButtonBaseStyle" TargetType="{x:Type ButtonBase}"> 
    <!-- Style stuff --> 
</Style> 
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonBaseStyle}"> 
    <!-- Additional style stuff for button only --> 
</Style> 
<Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource ButtonBaseStyle}"> 
    <!-- Additional style stuff for toggle button only --> 
</Style> 
<!-- more ButtonBase descendants here --> 
Cuestiones relacionadas