2010-09-20 13 views
28

he visto el siguiente hilo que está relacionada con mi pregunta:¿Cómo cambiar el color de fondo del cuadro de texto con discapacidad en WPF

WPF ComboBox: background color when disabled

Las ofertas anteriores con el cambio de la plantilla de contenido para un ComboBox. Estoy trabajando con WPF, soy un tanto nuevo en Estilos y plantillas, y quiero cambiar el color de fondo gris apagado de un TextBox deshabilitado a algún otro color. Utilizamos TextBoxes con frecuencia en nuestra aplicación y encontramos que la configuración de color predeterminada es difícil de leer.

He creado el siguiente intento de solución. Pero por supuesto, no funciona. ¿Alguien puede darme una opinión sobre por qué?

Upload Image

Respuesta

29

Por desgracia para el control de cuadro de texto, parece como que no es tan simple como la adición de un gatillo y cambiar el color de fondo cuando la condición de disparo es verdadera. Tienes que anular todo el ControlTemplate para lograr esto. A continuación se muestra un ejemplo de cómo se puede hacer esto:

<Window x:Class="StackOverflow.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.Resources> 
     <SolidColorBrush x:Key="DisabledForegroundBrush" Color="Red" /> 
     <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="White" /> 
     <Style TargetType="TextBox"> 
      <Setter Property="Background" Value="White"/> 
      <Setter Property="BorderBrush" Value="Black"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="TextBox"> 
         <Border Name="Bd" BorderThickness="{TemplateBinding BorderThickness}" 
              BorderBrush="{TemplateBinding BorderBrush}" 
              Background="{TemplateBinding Background}" 
              SnapsToDevicePixels="true"> 
          <ScrollViewer Name="PART_ContentHost" Background="{TemplateBinding Background}" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
         </Border> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsEnabled" Value="False"> 
           <Setter Value="{StaticResource DisabledBackgroundBrush}" Property="Background" /> 
           <Setter Value="{StaticResource DisabledForegroundBrush}" Property="Foreground" /> 
           <Setter TargetName="PART_ContentHost" Property="Background" Value="Blue"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 


    </Window.Resources> 

    <Canvas> 
     <TextBox Text="TextBox" IsEnabled="False"/> 
     <TextBox Text="TextBox" IsEnabled="True" Canvas.Top="25"/> 
    </Canvas>    
</Window>  

EDIT:

En respuesta a su pregunta, He intentado añadir el estilo ComboBox a mi primera respuesta arriba y pude integrarlo sin errores. Aunque no estoy seguro si se comporta como quisieras. Acabo de copiar y pegar lo que está en el enlace que especificó.

<Window x:Class="StackOverflow.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:StackOverflow" 
     Title="MainWindow" Height="350" Width="525" 
     x:Name="window"> 
    <Window.Resources> 
     <SolidColorBrush x:Key="DisabledForegroundBrush" Color="Red" /> 
     <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="Blue" /> 

     <LinearGradientBrush x:Key="NormalBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#FFF" Offset="0.0"/> 
        <GradientStop Color="#CCC" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="HorizontalNormalBrush" StartPoint="0,0" EndPoint="1,0"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#FFF" Offset="0.0"/> 
        <GradientStop Color="#CCC" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="LightBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#FFF" Offset="0.0"/> 
        <GradientStop Color="#EEE" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="HorizontalLightBrush" StartPoint="0,0" EndPoint="1,0"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#FFF" Offset="0.0"/> 
        <GradientStop Color="#EEE" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="DarkBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#FFF" Offset="0.0"/> 
        <GradientStop Color="#AAA" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="PressedBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#BBB" Offset="0.0"/> 
        <GradientStop Color="#EEE" Offset="0.1"/> 
        <GradientStop Color="#EEE" Offset="0.9"/> 
        <GradientStop Color="#FFF" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" /> 

     <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" /> 

     <!-- Border Brushes --> 

     <LinearGradientBrush x:Key="NormalBorderBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#CCC" Offset="0.0"/> 
        <GradientStop Color="#444" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="HorizontalNormalBorderBrush" StartPoint="0,0" EndPoint="1,0"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#CCC" Offset="0.0"/> 
        <GradientStop Color="#444" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="DefaultedBorderBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#777" Offset="0.0"/> 
        <GradientStop Color="#000" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="PressedBorderBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Color="#444" Offset="0.0"/> 
        <GradientStop Color="#888" Offset="1.0"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <SolidColorBrush x:Key="DisabledBorderBrush" Color="#AAA" /> 

     <SolidColorBrush x:Key="SolidBorderBrush" Color="#888" /> 

     <SolidColorBrush x:Key="LightBorderBrush" Color="#AAA" /> 

     <!-- Miscellaneous Brushes --> 
     <SolidColorBrush x:Key="GlyphBrush" Color="#444" /> 

     <SolidColorBrush x:Key="LightColorBrush" Color="#DDD" /> 

     <ControlTemplate x:Key="ComboBoxToggleButton" TargetType="ToggleButton"> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition /> 
        <ColumnDefinition Width="20" /> 
       </Grid.ColumnDefinitions> 
       <Border 
     x:Name="Border" 
     Grid.ColumnSpan="2" 
     CornerRadius="2" 
     Background="{StaticResource NormalBrush}" 
     BorderBrush="{StaticResource NormalBorderBrush}" 
     BorderThickness="1" /> 
       <Border 
     Grid.Column="0" 
     CornerRadius="2,0,0,2" 
     Margin="1" 
     Background="{StaticResource WindowBackgroundBrush}" 
     BorderBrush="{StaticResource NormalBorderBrush}" 
     BorderThickness="0,0,1,0" /> 
       <Path 
     x:Name="Arrow" 
     Grid.Column="1"  
     Fill="{StaticResource GlyphBrush}" 
     HorizontalAlignment="Center" 
     VerticalAlignment="Center" 
     Data="M 0 0 L 4 4 L 8 0 Z"/> 
      </Grid> 
      <ControlTemplate.Triggers> 
       <Trigger Property="ToggleButton.IsMouseOver" Value="true"> 
        <Setter TargetName="Border" Property="Background" Value="{StaticResource DarkBrush}" /> 
       </Trigger> 
       <Trigger Property="ToggleButton.IsChecked" Value="true"> 
        <Setter TargetName="Border" Property="Background" Value="{StaticResource PressedBrush}" /> 
       </Trigger> 
       <Trigger Property="IsEnabled" Value="False"> 
        <Setter TargetName="Border" Property="Background" Value="{StaticResource DisabledBackgroundBrush}" /> 
        <Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource DisabledBorderBrush}" /> 
        <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/> 
        <Setter TargetName="Arrow" Property="Fill" Value="{StaticResource DisabledForegroundBrush}" /> 
       </Trigger> 
      </ControlTemplate.Triggers> 
     </ControlTemplate> 

     <ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox"> 
      <Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" /> 
     </ControlTemplate> 

     <Style x:Key="{x:Type ComboBox}" TargetType="ComboBox"> 
      <Setter Property="SnapsToDevicePixels" Value="true"/> 
      <Setter Property="OverridesDefaultStyle" Value="true"/> 
      <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/> 
      <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/> 
      <Setter Property="ScrollViewer.CanContentScroll" Value="true"/> 
      <Setter Property="MinWidth" Value="120"/> 
      <Setter Property="MinHeight" Value="20"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="ComboBox"> 
         <Grid> 
          <ToggleButton 
      Name="ToggleButton" 
      Template="{StaticResource ComboBoxToggleButton}" 
      Grid.Column="2" 
      Focusable="false" 
      IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}" 
      ClickMode="Press"> 
          </ToggleButton> 
          <ContentPresenter 
      Name="ContentSite" 
      IsHitTestVisible="False" 
      Content="{TemplateBinding SelectionBoxItem}" 
      ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" 
      ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" 
      Margin="3,3,23,3" 
      VerticalAlignment="Center" 
      HorizontalAlignment="Left" /> 
          <TextBox x:Name="PART_EditableTextBox" 
      Style="{x:Null}" 
      Template="{StaticResource ComboBoxTextBox}" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Center" 
      Margin="3,3,23,3" 
      Focusable="True" 
      Background="Transparent" 
      Visibility="Hidden" 
      IsReadOnly="{TemplateBinding IsReadOnly}"/> 
          <Popup 
      Name="Popup" 
      Placement="Bottom" 
      IsOpen="{TemplateBinding IsDropDownOpen}" 
      AllowsTransparency="True" 
      Focusable="False" 
      PopupAnimation="Slide"> 
           <Grid 
       Name="DropDown" 
       SnapsToDevicePixels="True"     
       MinWidth="{TemplateBinding ActualWidth}" 
       MaxHeight="{TemplateBinding MaxDropDownHeight}"> 
            <Border 
       x:Name="DropDownBorder" 
       Background="{StaticResource WindowBackgroundBrush}" 
       BorderThickness="1" 
       BorderBrush="{StaticResource SolidBorderBrush}"/> 
            <ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True"> 
             <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" /> 
            </ScrollViewer> 
           </Grid> 
          </Popup> 
         </Grid> 
         <ControlTemplate.Triggers> 
          <Trigger Property="HasItems" Value="false"> 
           <Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/> 
          </Trigger> 
          <Trigger Property="IsEnabled" Value="false"> 
           <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/> 
          </Trigger> 
          <Trigger Property="IsGrouping" Value="true"> 
           <Setter Property="ScrollViewer.CanContentScroll" Value="false"/> 
          </Trigger> 
          <Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="true"> 
           <Setter TargetName="DropDownBorder" Property="CornerRadius" Value="4"/> 
           <Setter TargetName="DropDownBorder" Property="Margin" Value="0,2,0,0"/> 
          </Trigger> 
          <Trigger Property="IsEditable" 
       Value="true"> 
           <Setter Property="IsTabStop" Value="false"/> 
           <Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/> 
           <Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
      <Style.Triggers> 
      </Style.Triggers> 
     </Style> 

     <Style TargetType="TextBox"> 
      <Setter Property="Background" Value="White"/> 
      <Setter Property="BorderBrush" Value="Black"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="TextBox"> 
         <Border Name="Bd" BorderThickness="{TemplateBinding BorderThickness}" 
              BorderBrush="{TemplateBinding BorderBrush}" 
              Background="{TemplateBinding Background}" 
              SnapsToDevicePixels="true"> 
          <ScrollViewer Name="PART_ContentHost" Background="{TemplateBinding Background}" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 
         </Border> 
         <ControlTemplate.Triggers> 
          <Trigger Property="IsEnabled" Value="False"> 
           <Setter Value="{StaticResource DisabledBackgroundBrush}" Property="Background" /> 
           <Setter Value="{StaticResource DisabledForegroundBrush}" Property="Foreground" /> 
           <Setter TargetName="PART_ContentHost" Property="Background" Value="{StaticResource DisabledBackgroundBrush}"/> 
          </Trigger> 
         </ControlTemplate.Triggers> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </Window.Resources> 

    <StackPanel> 
     <TextBox IsEnabled="False">TextBox</TextBox> 
     <ComboBox IsEnabled="False"/> 
    </StackPanel> 
</Window> 
+0

El ejemplo anterior funcionó en mis pruebas. ¡Gracias! Me preguntaba si podría agregar un seguimiento. Necesito una funcionalidad similar para el ComboBox, y parece que me la entregan en bandeja de plata con este enlace: http://msdn.microsoft.com/en-us/library/ms752094%28v=VS.85%29. aspx Sin embargo, tengo dificultades para combinar los dos. Si coloco el estilo anterior para el cuadro de texto y la plantilla de contenido del enlace al que se hace referencia en un archivo "Window.Resources", produce errores de sintaxis. ¿Puedes darme una guía sobre esto? –

+0

¿Qué errores está obteniendo? Bien, intentaré integrar el ControlTemplate para el ComboBox en mi ejemplo anterior y ver si puedo hacerlo funcionar. Me pondré en contacto con usted en esto. – ASanch

+0

Mira el XAML en mi EDIT de arriba. – ASanch

1

Nunca se utiliza el ControlTemplate ha definido. Además, desea un Estilo, no (necesariamente) una Plantilla de Control.

Creo que quieres algo como lo siguiente:

<Canvas.Resources> 
     <SolidColorBrush x:Key="DisabledForegroundBrush" Color="Red" /> 
     <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="White" /> 
     <Style TargetType="{x:Type TextBox}"> 
      <Style.Triggers> 
       <Trigger Property="IsEnabled" Value="False"> 
        <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}" /> 
        <Setter Property="Background" Value="{StaticResource DisabledBackgroundBrush}" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
</Canvas.Resources> 
+0

Wonko the Sane (que es un gran nombre de pantalla), ... No pude hacer funcionar el ejemplo anterior (no pareció modificar nada). Es elegante, sin embargo, y mucho más corto que la respuesta a continuación, por lo que sería genial ... pero sin suerte. Gracias por su respuesta. –

+0

@ user452763 (no es tan memorable como nombre de usuario) - sí, karmicpuppet es correcto. Creo que tiene que ver con la forma en que el control TextBox se compone de otros controles. –

7

Para esta situación me gusta poner Focusable=false y establecer el color de fondo a mi valor deseado (en un disparador enlazado a datos). Esto es quizás un poco hacky, pero también lo es reescribir la plantilla de control para todo el TextBox. Una alternativa a Focusable es IsReadyOnly, pero eso no funciona con tantos controles. Sin embargo, asegura que el caret desaparezca.

2

Intente evitar la redefinición de las plantillas de control donde pueda. Tienden a agregar una gran cantidad de código y pueden ser difíciles de mantener con el tiempo.

me gustaría utilizar el código siguiente en el evento Loaded:

ClassicBorderDecorator o = VisualTreeHelper.GetChild(this.textBox1, 0) as ClassicBorderDecorator; 
if (o != null) 
{ 
    o.Background = new SolidColorBrush(Colors.Transparent); 
} 
23

Se puede utilizar el siguiente fragmento:

En lugar de comprobar la propiedad IsEnable, utilice la propiedad IsReadOnly de control de cuadro de texto.

<Style TargetType="{x:Type TextBox}"> 
    <Setter Property="Background" Value="LightSkyBlue" /> 
    <Style.Triggers> 
     <Trigger Property="IsReadOnly" Value="True"> 
      <Setter Property="Background" Value="Red" /> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

Si necesita aplicarlo para todos los controles del cuadro de texto, utilice el código anterior. Para el cuadro de texto específico, simplemente configure la clave y aplique el estilo a ese cuadro de texto.

+0

En mi caso eso no funcionará, porque el control es parte de un grupo de controles en un panel que está deshabilitado. Cuando el panel está desactivado, el campo de texto está implícitamente deshabilitado, y tan pronto como se deshabilita, se vuelve a, por ejemplo, un fondo blanco sólido en lugar del fondo traslúcido que configuré. – Triynko

1

Si observa la plantilla del cuadro de texto, observará que la plantilla tiene un activador para la propiedad IsEnabled False, y establece su color de fondo del elemento de borde "Bd" en SystemColors.ControlBrushKey.

Si anula este color en un estilo, logrará lo que quiere hacer.

<Style TargetType="{x:Type TextBox}"> 
    <Style.Resources> 
    <SolidColorBrush 
     x:Key="{x:Static SystemColors.ControlBrushKey}" 
     Color="{StaticResource MyNewTextBoxBackgroundColor}" /> 
    </Style.Resources> 
</Style> 
0
By adding <Window.Resources> after <Window> and before <Grid> will make your text box behave like normal winforms textbox. 

<Window x:Class="..." Height="330" Width="600" Loaded="Window_Loaded" WindowStartupLocation="CenterOwner"> 

<Window.Resources> 
    <Style TargetType="{x:Type TextBox}"> 
     <Style.Triggers> 
      <Trigger Property="IsReadOnly" Value="True"> 
       <Setter Property="Background" Value="LightGray" /> 
      </Trigger> 
      <Trigger Property="IsReadOnly" Value="False"> 
       <Setter Property="Background" Value="White" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</Window.Resources> 

<Grid> 

Código tomado de la página web siguiente:

wpf: Selecting the Text in TextBox with IsReadOnly = true?

Y el estilo modificado para que coincida con WinForms. (Su apariencia está habilitada = false, no solo readonly = true)

Y, por supuesto, su cuadro de texto debe tener el atributo IsReadOnly = "True" establecido.

Cuestiones relacionadas