【问题标题】:How to change disabled background color of TextBox in WPF如何在 WPF 中更改 TextBox 的禁用背景颜色
【发布时间】:2011-04-14 16:45:57
【问题描述】:

我看到了与我的问题相关的以下线程:

WPF ComboBox: background color when disabled

以上内容涉及更改ComboBox 的内容模板。我正在使用 WPF,对样式和模板有些陌生,我想将禁用的 TextBox 的暗灰色背景颜色更改为其他颜色。我们在应用程序中经常使用TextBoxes,我们发现默认颜色设置难以阅读。

我设计了以下解决方案尝试。但是,当然,它不起作用。有人可以就为什么给我一个意见吗?

【问题讨论】:

    标签: wpf templates textbox background controls


    【解决方案1】:

    不幸的是,对于 TextBox 控件,它看起来不像只是在触发条件为真时添加触发器并更改背景颜色那么简单。您必须覆盖整个 ControlTemplate 才能实现此目的。下面是一个关于如何执行此操作的示例:

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

    编辑:

    针对您的问题,我尝试将 ComboBox 样式添加到我上面的原始答案中,并且我能够将其集成而不会出错。我不确定它是否表现得像你想要的那样。我只是复制粘贴了您指定的链接中的内容。

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

    【讨论】:

    • 上面的例子在我的测试中确实有效。谢谢!我想知道我是否可以添加一个后续。我需要 ComboBox 的类似功能,这似乎是通过以下链接在银盘上交给我的:msdn.microsoft.com/en-us/library/ms752094%28v=VS.85%29.aspx 但是,我很难将两者结合起来。如果我将 TextBox 的上述样式和引用链接中的内容模板都放入一个“Window.Resources”文件中,则会产生语法错误。你能给我这方面的指导吗?
    • 您遇到了什么错误?好吧,我将尝试将 ComboBox 的 ControlTemplate 集成到我上面的示例中,看看我是否可以使它工作。我会尽快回复你。
    • 在我上面的 EDIT 中查看 XAML。
    • KarmicPuppet,你真是个天才。以上所有工作。我一定是在某种程度上错误地处理了 Xml 编辑,并且没有关闭标签或其他东西。这个问题解决了,不知道你能不能自己回答一个高层次的问题?您能否推荐一个可以帮助人们掌握 Xaml 样式/控件模板的参考资料?浏览网站是有帮助的,但似乎都没有提供允许人们从“空白”页面制作上述解决方案的知识水平。再次感谢您的帮助。
    • 好吧,说实话,我真的不知道我可以推荐任何具体的参考资料。我个人已经习惯了这些样式/控件模板业务,为许多演示应用程序/原型编写了一堆自定义控件,我的参考资料通常是 MSDN 或特定主题的谷歌搜索。所以,对不起,我不能帮你。 (顺便说一句,你有没有机会接受我上面的回答是正确的?谢谢)。
    【解决方案2】:

    你可以使用下面的sn-p:

    不要检查 IsEnable 属性,而是使用 TextBox 控件的 IsReadonly 属性。

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

    如果您需要将其应用于所有文本框控件,请使用上述代码。 对于特定的文本框,只需设置键并将样式应用于该文本框。

    【讨论】:

    • 在我的情况下这不起作用,因为该控件是禁用的面板中一组控件的一部分。当面板被禁用时,文本字段被隐式禁用,一旦它被禁用,它就会恢复为例如纯白色背景而不是我设置的半透明背景。
    • 设置 IsReadonly 将意味着 Windows 7/10 在鼠标悬停时仍会在 TexBox 周围呈现蓝色“输入控件”边框,这可能不是所需的行为。只是需要注意的事情。
    【解决方案3】:

    对于这种情况,我喜欢设置Focusable=false 并将背景颜色设置为我想要的值(在数据绑定触发器中)。这可能有点 hacky,但重写整个 TextBox 的控制模板也是如此。 Focusable 的替代品是IsReadyOnly,但这不适用于尽可能多的控件。不过,它确实确保插入符号消失。

    【讨论】:

      【解决方案4】:

      您从不使用您定义的 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>
      

      【讨论】:

      • Wonko the Sane(这是一个很棒的网名),......我无法让上面的例子工作(它似乎没有修改任何东西)。然而,它很优雅,并且比下面的响应短得多,所以它会很棒......但没有运气。感谢您的回复。
      • @user452763(不太容易记住的网名)——是的,karmicpuppet 是正确的。我认为这与 TextBox 控件由其他控件组成的方式有关。
      【解决方案5】:

      如果您查看文本框的模板,您会注意到该模板具有 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>
      

      【讨论】:

        【解决方案6】:

        尽量避免重新定义控件模板。它们往往会增加大量代码开销,并且随着时间的推移会变得难以维护。

        我会在 Loaded 事件中使用以下代码:

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

        【讨论】:

          【解决方案7】:
          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: Selecting the Text in TextBox with IsReadOnly = true?

          并修改样式以匹配 winforms。 (他们的外观是启用=假,而不是只读=真)

          当然,您的文本框必须设置 IsReadOnly="True" 属性。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-24
            • 1970-01-01
            • 2012-05-27
            • 2012-04-11
            • 1970-01-01
            • 2015-08-22
            相关资源
            最近更新 更多