Как изменить отключенный цвет фона TextBox в WPF

Я видел следующую ветку, которая связана с моим вопросом:

WPF ComboBox: цвет фона при отключении

Вышеизложенное касается изменения шаблона контента для ComboBox, Я работаю с WPF, я немного новичок в стилях и шаблонах, и я хочу изменить унылый серый цвет фона отключенного TextBox в другой цвет. Мы используем TextBoxes часто в нашем приложении, и мы находим настройки цвета по умолчанию трудно читать.

Я создал следующую попытку решения. Но, конечно, это не работает. Может кто-нибудь дать мне мнение о том, почему?

Загрузить изображение

7 ответов

Решение

К сожалению, для элемента управления TextBox кажется, что это не так просто, как просто добавить триггер и изменить цвет фона, когда условие триггера выполнено. Вы должны переопределить весь ControlTemplate для достижения этого. Ниже приведен один пример того, как вы можете сделать это:

<Window x:Class="Stackru.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>     

РЕДАКТИРОВАТЬ:

В ответ на ваш вопрос я попытался добавить стиль ComboBox к моему первоначальному ответу выше и смог интегрировать его без ошибок. Я не уверен, что если он ведет себя так, как вы этого хотели. Я просто скопировал то, что указано в указанной вами ссылке.

<Window x:Class="Stackru.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Stackru"
        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>

Вы можете использовать следующий фрагмент:

Вместо проверки свойства IsEnable используйте свойство IsReadonly элемента управления 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>

Если вам необходимо применить его ко всем элементам управления текстовым полем, используйте приведенный выше код. Для конкретного текстового поля просто установите ключ и примените стиль к этому текстовому полю.

Для этой ситуации мне нравится устанавливать Focusable=false и установите цвет фона на желаемое значение (в триггере с привязкой к данным). Это может быть немного странно, но так же переписывает шаблон управления для всего TextBox, Альтернатива Focusable является IsReadyOnly, но это не работает для стольких элементов управления. Это действительно гарантирует, что каретка исчезнет, ​​хотя.

Вы никогда не используете определенный вами шаблон ControlTemplate. Кроме того, вы хотите стиль, а не (обязательно) ControlTemplate.

Я думаю, что вы хотите что-то вроде следующего:

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

Если вы посмотрите на шаблон текстового поля, вы заметите, что в шаблоне есть триггер для свойства IsEnabled False, и для его цвета фона элемента границы "Bd" установлено значение SystemColors.ControlBrushKey.

Если вы переопределите этот цвет в стиле, он достигнет того, что вы хотите сделать.

<Style TargetType="{x:Type TextBox}">
  <Style.Resources>
    <SolidColorBrush 
       x:Key="{x:Static SystemColors.ControlBrushKey}" 
       Color="{StaticResource MyNewTextBoxBackgroundColor}" />
  </Style.Resources>
</Style>

Старайтесь избегать переопределения шаблонов управления, где вы можете. Они, как правило, добавляют много накладных расходов на код и со временем их становится трудно поддерживать.

Я бы использовал следующий код в событии Loaded:

ClassicBorderDecorator o = VisualTreeHelper.GetChild(this.textBox1, 0) as ClassicBorderDecorator;
if (o != null)
{
    o.Background = new SolidColorBrush(Colors.Transparent);
}
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>

Код взят со следующей веб-страницы:

wpf: выделение текста в TextBox с IsReadOnly = true?

И стиль изменен, чтобы соответствовать winforms. (Их появление включено = ложь, не только для чтения = истина)

И, конечно, в вашем текстовом поле должен быть установлен атрибут IsReadOnly="True".

Другие вопросы по тегам