我的TextBox控件模板有问题 [英] Having an issue with my TextBox control template

查看:71
本文介绍了我的TextBox控件模板有问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个简单的textBox模板,它只有两个边框,一个带有渐变背景.现在,我的特定问题是我希望能够将textBox的前景色设置为我想要的任何颜色,并使其正常工作.但是,我似乎无法同时使禁用的前景色和启用的前景色同时起作用.例如,如果将前景设置为红色,则在禁用textBox时,前景不会更改为禁用的颜色.我尝试在IsEnabled ="true"触发器中绑定前景,但这似乎不起作用.无论是否启用了文本框,前景始终保持红色.

能否请您查看下面的模板,并告诉我我做错了什么?另外,请向我指出自创建模板以来我可能犯的任何其他错误.

非常感谢.

  <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
  <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
  <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
  <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />


<Style x:Key="TextBoxControlTemplate1" TargetType="{x:Type TextBox}">
  <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
  <Setter Property="AllowDrop" Value="true"/>
  <Setter Property="Background" Value="#00000000"/>
  <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
  <Setter Property="VerticalContentAlignment" Value="Stretch"/>
  <Setter Property="FontFamily" Value="Segoe UI"/>
  <Setter Property="FontSize" Value="12"/>
  <Setter Property="Padding" Value="8,5,3,3"/>
  <Setter Property="BorderThickness" Value="0"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TextBox}">
        <Grid>
          <Border BorderBrush="#FF000000" BorderThickness="2,2,2,2" CornerRadius="5,5,5,5" Padding="0,0,0,0" Width="Auto" Height="Auto" Background="#FF000000"/>
          <Border x:Name="Border" BorderBrush="#FFFFFFFF" BorderThickness="1,1,1,1" CornerRadius="5,5,5,5" Padding="0,0,0,0" Width="Auto" Height="Auto" Margin="2,2,2,2">
            <Border.Background>
              <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF000000" Offset="0"/>
                <GradientStop Color="#FF4D4D4D" Offset="1"/>
              </LinearGradientBrush>
            </Border.Background>
          </Border>
          <ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/>
            <Setter Property="BorderBrush" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/>
            <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
          </Trigger>
          <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>


<TextBox Text="TEST" TextWrapping="Wrap" Canvas.Top="293.761" Canvas.Left="112" Style="{DynamicResource TextBoxControlTemplate1}" Height="28.724" Width="232.25" IsTabStop="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsEnabled="True" Foreground="#FFFF0000"/>

解决方案

这里有一些不同的问题对您不利.首先是在控件实例上设置特定的前景值,该值比对Style中的Trigger s设置的控件本身属性的优先级更高.这与在ControlTemplate 元素上设置的属性不同,例如边界".您使用Trigger设置Border属性的方式就说明了这一点.通常,您还希望使用TemplateBinding来获取控件实例上设置的默认值,例如Background,这些值目前被忽略.

要在样式控件上的两个属性值之间切换,就像要使用Foreground一样,可以在Style中使用SetterTrigger来提供默认值和备用值.实例上设置的值仍然会覆盖它.如果您想禁止覆盖Trigger的实例,请将其设置为"Border" Trigger一样,在其中为ControlTemplate中的元素设置值.

我建议的最后一个更改是将要拉入Style的笔刷切换到StaticResource.在这种情况下,它可能没有什么区别,但是在某些情况下,可以将默认的Style拉到一个上下文中,该上下文没有从声明该文件的文件中引用周围的资源.使用Static将确保它无论在哪里使用,都将包括那些资源.您可能不会遇到这种情况,但是在设置这样的样式/模板时,这是个好习惯.

在您的代码中进行了以下改进:

<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />

<Style x:Key="TextBoxControlTemplate1" TargetType="{x:Type TextBox}">
    <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="Background">
        <Setter.Value>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF000000" Offset="0"/>
                <GradientStop Color="#FF4D4D4D" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="FontFamily" Value="Segoe UI"/>
    <Setter Property="FontSize" Value="12"/>
    <Setter Property="Padding" Value="8,5,3,3"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Setter Property="BorderBrush" Value="#FF000000"/>
    <Setter Property="Foreground" Value="Red" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <Grid>
                    <!--Take advantage of containment when possible to let the layout engine help you!-->
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5" Padding="0" Background="#FF000000"/>
                    <Border x:Name="Border" BorderBrush="#FFFFFFFF" BorderThickness="1" CornerRadius="5" Padding="0" Margin="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"/>
                    <ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Background" Value="{StaticResource DisabledBackgroundBrush}" TargetName="Border"/>
                        <Setter Property="BorderBrush" Value="{StaticResource DisabledBackgroundBrush}" TargetName="Border"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
        </Trigger>
    </Style.Triggers>
</Style>

TextBox仅使用Style设置:

<TextBox Text="TEST" TextWrapping="Wrap" Canvas.Top="293.761" Canvas.Left="112" Style="{DynamicResource TextBoxControlTemplate1}" 
         Height="28.724" Width="232.25" IsTabStop="False" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" />

I am working on a simple textBox template, which is just two borders, one with a gradient background. Now, my specific issue is that I want to be able to set the foreground color of the textBox to whatever color I want and have it work correctly. However, I can't seem to get both the disabled foreground and enabled foreground colors to work together. If I set the foreground to red for example, when I disable the textBox, the foreground doesn't get changed to my disabled color. I tried binding the foreground in the IsEnabled="true" trigger but that doesn't seem to work. The foreground always stays red, no matter if the textBox is enabled or not.

Can you please take a look at the below template and tell me what I am doing wrong? Also, please point out to me any other mistakes I may have made since I am new at creating templates.

Thanks a lot.

  <SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
  <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
  <SolidColorBrush x:Key="WindowBackgroundBrush" Color="#FFF" />
  <SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />


<Style x:Key="TextBoxControlTemplate1" TargetType="{x:Type TextBox}">
  <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
  <Setter Property="AllowDrop" Value="true"/>
  <Setter Property="Background" Value="#00000000"/>
  <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
  <Setter Property="VerticalContentAlignment" Value="Stretch"/>
  <Setter Property="FontFamily" Value="Segoe UI"/>
  <Setter Property="FontSize" Value="12"/>
  <Setter Property="Padding" Value="8,5,3,3"/>
  <Setter Property="BorderThickness" Value="0"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type TextBox}">
        <Grid>
          <Border BorderBrush="#FF000000" BorderThickness="2,2,2,2" CornerRadius="5,5,5,5" Padding="0,0,0,0" Width="Auto" Height="Auto" Background="#FF000000"/>
          <Border x:Name="Border" BorderBrush="#FFFFFFFF" BorderThickness="1,1,1,1" CornerRadius="5,5,5,5" Padding="0,0,0,0" Width="Auto" Height="Auto" Margin="2,2,2,2">
            <Border.Background>
              <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF000000" Offset="0"/>
                <GradientStop Color="#FF4D4D4D" Offset="1"/>
              </LinearGradientBrush>
            </Border.Background>
          </Border>
          <ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/>
            <Setter Property="BorderBrush" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border"/>
            <Setter Property="Foreground" Value="{DynamicResource DisabledForegroundBrush}"/>
          </Trigger>
          <Trigger Property="IsEnabled" Value="True">
            <Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>


<TextBox Text="TEST" TextWrapping="Wrap" Canvas.Top="293.761" Canvas.Left="112" Style="{DynamicResource TextBoxControlTemplate1}" Height="28.724" Width="232.25" IsTabStop="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" IsEnabled="True" Foreground="#FFFF0000"/>

解决方案

There are a few different issues here all working against you. The first is that you're setting a specific Foreground value on your control instance, which has a higher priority than values set from Triggers in your Style for properties of the control itself. This is different than properties set on elements inside the ControlTemplate, like "Border". The way you're using Triggers to set the Border properties is illustrating that. Normally you would also want to use TemplateBindings to pull in values set on your control instance as defaults, like Background, which are currently being ignored.

To switch between two values of a property on your styled control, like you want to do with Foreground, you can use a Setter and a Trigger in your Style to provide a default and alternate value. This is still subject to being overridden by a value set on an instance. If you want to disallow instances overriding a Trigger set it up like the "Border" Trigger where you're setting values on elements inside the ControlTemplate.

The last change I'd recommend is switching to StaticResource for the Brushes you're pulling into your Style. In this case it probably won't make a difference, but in some cases a default Style can get pulled into a context that doesn't have any reference to the surrounding Resources from the file it was declared in. Using Static will guarantee that it will include those Resources no matter where it gets used. You may not run into this but it's a good habit to get into when setting up Styles/Templates like this.

Here's your code with those improvements:

<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />

<Style x:Key="TextBoxControlTemplate1" TargetType="{x:Type TextBox}">
    <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
    <Setter Property="AllowDrop" Value="true"/>
    <Setter Property="Background">
        <Setter.Value>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF000000" Offset="0"/>
                <GradientStop Color="#FF4D4D4D" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="FontFamily" Value="Segoe UI"/>
    <Setter Property="FontSize" Value="12"/>
    <Setter Property="Padding" Value="8,5,3,3"/>
    <Setter Property="BorderThickness" Value="2"/>
    <Setter Property="BorderBrush" Value="#FF000000"/>
    <Setter Property="Foreground" Value="Red" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
                <Grid>
                    <!--Take advantage of containment when possible to let the layout engine help you!-->
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5" Padding="0" Background="#FF000000"/>
                    <Border x:Name="Border" BorderBrush="#FFFFFFFF" BorderThickness="1" CornerRadius="5" Padding="0" Margin="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"/>
                    <ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled" Value="False">
                        <Setter Property="Background" Value="{StaticResource DisabledBackgroundBrush}" TargetName="Border"/>
                        <Setter Property="BorderBrush" Value="{StaticResource DisabledBackgroundBrush}" TargetName="Border"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="False">
            <Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
        </Trigger>
    </Style.Triggers>
</Style>

And the TextBox using only the Style settings:

<TextBox Text="TEST" TextWrapping="Wrap" Canvas.Top="293.761" Canvas.Left="112" Style="{DynamicResource TextBoxControlTemplate1}" 
         Height="28.724" Width="232.25" IsTabStop="False" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" />

这篇关于我的TextBox控件模板有问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆