2010-09-20 21 views
28

Ho visto questo thread che è legato alla mia domanda:Come cambiare colore di sfondo disabilitata di TextBox in WPF

WPF ComboBox: background color when disabled

Le suddette offerte con il cambiamento del modello di contenuti per un ComboBox. Sto lavorando con WPF, sono un po 'nuovo per Stili e Modelli, e voglio cambiare il colore di sfondo grigio opaco di un TextBox disattivato con un altro colore. Usiamo TextBoxes frequentemente nella nostra applicazione e troviamo le impostazioni del colore di default difficili da leggere.

Ho creato il seguente tentativo di soluzione. Ma ovviamente, non funziona. Qualcuno può darmi un parere sul perché?

Upload Image

risposta

29

Purtroppo per il controllo TextBox, appare come non è così semplice come solo l'aggiunta di un trigger e cambiando il colore di sfondo quando la condizione di trigger è vera. È necessario sovrascrivere l'intero ControlTemplate per ottenere ciò. Di seguito è riportato un esempio di come si potrebbe fare questo:

<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:

In risposta alla tua domanda, ho provato ad aggiungere lo stile ComboBox per la mia risposta originale sopra e sono stato in grado di integrarla senza errori. Non sono sicuro se si comporti come volevi. Ho semplicemente copiato e incollato cosa c'è nel link specificato.

<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

L'esempio sopra ha funzionato nei miei test. Grazie! Mi chiedevo se potessi aggiungere un seguito. Ho bisogno di funzionalità simili per il ComboBox, e questo mi sembra essere passato su un piatto d'argento con questo link: http://msdn.microsoft.com/en-us/library/ms752094%28v=VS.85%29. aspx Tuttavia, ho difficoltà a combinare i due. Se metto sia lo Stile sopra per il TextBox, sia il Template Contenuto dal link referenziato in un file "Window.Resources", produce errori di sintassi. Puoi darmi una guida su questo? –

+0

Quali errori stai ottenendo? Bene, cercherò di integrare il ControlTemplate per il ComboBox nel mio esempio sopra e vedere se riesco a farlo funzionare. Ti risponderò su questo. – ASanch

+0

Controlla lo XAML nel mio EDIT qui sopra. – ASanch

1

non si utilizza mai il ControlTemplate definito. Inoltre, vuoi uno stile, non (necessariamente) un ControlTemplate.

Penso che si desidera qualcosa di simile al seguente:

<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 (che è un ottimo nome per lo schermo), ... Non ho potuto ottenere l'esempio precedente per funzionare (non sembra modificare nulla). È elegante, tuttavia, e molto più breve della risposta qui sotto, quindi sarebbe fantastico ... ma senza fortuna. Grazie per la vostra risposta. –

+0

@ user452763 (non proprio un nome di schermo memorabile) - sì, karmicpuppet è corretto. Credo che abbia a che fare con il modo in cui il controllo TextBox è composto da altri controlli. –

7

Per questa situazione mi piace impostare Focusable=false e impostare il colore di sfondo per il mio valore desiderato (in un trigger associato ai dati). Questo è forse un po 'hacky, ma così è riscrivere il modello di controllo per l'intero TextBox. Un'alternativa a Focusable è IsReadyOnly, ma ciò non funziona per tutti i controlli. Fa sì che il cursore scompaia, però.

2

Cercare di evitare la ridefinizione dei modelli di controllo dove è possibile. Tendono ad aggiungere un sacco di overhead del codice e possono diventare difficili da mantenere nel tempo.

Vorrei utilizzare il codice riportato di seguito l'evento Loaded:

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

È possibile utilizzare il frammento di seguito:

Invece di controllare per la proprietà IsEnable, utilizzare la proprietà IsReadOnly di controllo TextBox.

<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> 

Se è necessario applicarlo per tutti i controlli della casella di testo, utilizzare il codice precedente. Per una casella di testo specifica, basta impostare la chiave e applicare lo stile a quella casella di testo.

+0

Nel mio caso non funzionerà, perché il controllo fa parte di un gruppo di controlli in un pannello che è disabilitato. Quando il pannello è disabilitato, il campo di testo viene disabilitato implicitamente e, non appena disattivato, ritorna, ad esempio, a uno sfondo bianco pieno anziché allo sfondo traslucido che ho impostato. – Triynko

1

Se si guarda il modello della casella di testo, si noterà che il modello ha un trigger per la proprietà IsEnabled False e imposta il colore di sfondo "Bd" del bordo elemento su SystemColors.ControlBrushKey.

Se si sostituisce questo colore in uno stile, otterrà ciò che si vuole fare.

<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> 

codice preso dalla seguente pagina web:

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

E lo stile modificato per corrispondere WinForms. (Il loro aspetto è abilitato = falso, non di sola lettura = vero)

E ovviamente la tua casella di testo deve avere IsReadOnly = "True" set di attributi.

Problemi correlati