我的 TextBox 控件模板有问题

发布于 2024-08-22 09:37:18 字数 3344 浏览 2 评论 0原文

我正在开发一个简单的文本框模板,它只有两个边框,一个带有渐变背景。现在,我的具体问题是我希望能够将文本框的前景色设置为我想要的任何颜色并使其正常工作。但是,我似乎无法让禁用的前景色和启用的前景色一起工作。例如,如果我将前景设置为红色,则当我禁用文本框时,前景不会更改为我禁用的颜色。我尝试在 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"/>

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伏妖词 2024-08-29 09:37:18

这里有一些不同的问题都对你不利。第一个是您在控件实例上设置特定的 Foreground 值,该值的优先级高于 Style 中为控件属性设置的 Trigger 值本身。这与ControlTemplate内部元素上设置的属性不同,例如“Border”。您使用Trigger 设置Border 属性的方式就说明了这一点。通常,您还需要使用 TemplateBinding 来引入在控件实例上设置的默认值,例如 Background,这些值当前被忽略。

要在样式化控件上的属性的两个值之间切换(就像您想要对 Foreground 所做的那样),您可以使用 SetterTrigger在您的 Style 中提供默认值和备用值。这仍然可能被实例上设置的值覆盖。如果您想禁止实例覆盖 Trigger,请将其设置为“Border”Trigger,您可以在 ControlTemplate 内的元素上设置值。

我建议的最后一个更改是将您拉入 Style 的画笔切换到 StaticResource。在这种情况下,它可能不会产生任何影响,但在某些情况下,默认样式可以被拉入一个上下文,该上下文没有对其声明的文件中的周围资源有任何引用。使用静态将保证它将包括这些资源,无论其在何处使用。您可能不会遇到这种情况,但在设置这样的样式/模板时这是一个好习惯。

以下是经过这些改进的代码:

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

以及仅使用 Style 设置的 TextBox

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

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" />
无所谓啦 2024-08-29 09:37:18

可以尝试的几个想法:

  1. 摆脱其中一个触发因素。有两个相反的触发因素可能不是一个好主意。我将直接在 Border 声明上设置默认的 BackgroundBorderBrushForeground,并删除 >Enabled="True" 触发器。然后,调试只需正确设置 Enabled="False" 触发器即可。

  2. TargetName 属性添加到 Enabled="False" 触发器的设置器。

  3. 这是一个不太可能的方案,但请使用 UIElement.IsEnabled 而不仅仅是 IsEnabled,如下所示:.

希望我在这里所说的有帮助!

A couple ideas to try:

  1. Get rid of one of your triggers. Having two opposing triggers may not be a good idea. I would set the default Background, BorderBrush, and Foreground directly on your Border declaration, and remove the Enabled="True" trigger. Then, debugging is only a matter of getting the Enabled="False" trigger right.

  2. Add the TargetName property to setter for your Enabled="False" trigger.

  3. This is a longshot, but use UIElement.IsEnabled instead of just IsEnabled, like this: <Trigger Property="UIElement.IsEnabled">.

Hope something I've said here helps!

仙气飘飘 2024-08-29 09:37:18

可能的原因是您的 DisabledBackgroundBrush 在您使用样式时不可见。请尝试将样式添加到 ControlTemplate 的资源中:

<ControlTemplate TargetType="{x:Type TextBox}">
    <ControlTemplate.Resources>
        <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
        ...
    </ControlTemplate.Resources>
    ...

顺便说一句,您的控件模板不支持您的属性值。
例如,您也许应该

<ScrollViewer Margin="{TemplateBinding Padding}" x:Name="PART_ContentHost"/>

在控件模板中使用类似的内容。

The possible reason is that your DisabledBackgroundBrush is not visible at the point where you use your style. Please try to add the styles into the ControlTemplate's resources:

<ControlTemplate TargetType="{x:Type TextBox}">
    <ControlTemplate.Resources>
        <SolidColorBrush x:Key="DisabledBackgroundBrush" Color="#EEE" />
        ...
    </ControlTemplate.Resources>
    ...

By the way, your control template doesn't honour the values of your properties.
For example, you should perhaps use something like

<ScrollViewer Margin="{TemplateBinding Padding}" x:Name="PART_ContentHost"/>

in your control template.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文