textBox的自定义模板,在IsEnabled = false时不符合我的要求

时间:2011-06-01 13:19:06

标签: wpf xaml templating operator-precedence isenabled

我的问题与此类似: Having an issue with my TextBox control template

但我想更进一步:

我的问题很简单: 我有模板控件(标签,文本框,复选框等......)。每个控件都有默认值,可以通过设置控件实例的属性值在运行时覆盖它们。无论为属性设置了什么值,我决定在IsEnabled = false时使用的值都应该占优势。

现在,我知道WPF中的值优先级阻止了这种行为的简单实现(正如我在另一个问题中所学到的那样:http://msdn.microsoft.com/en-us/library/ms743230.aspx

但我设法找到了一个很好的工作方式,除了TextBox中的Foreground属性。 (只有这个具体情况)

所以,只需要处理前景值,这就是我在标签上做的事情:(为了更清晰,我摆脱了所有其他属性)

    <Style TargetType="Label">
        <Setter Property="Foreground" Value="Blue"/>

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Label">
                    <Border>
                        <ContentPresenter Name="ContentSite"/>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter TargetName="ContentSite" Property="TextBlock.Foreground" Value="Red"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

所以基本上,默认情况下,Label会有一个蓝色文本,我可以通过在后面的代码中执行:myLabel.Foreground = Brushes.Green覆盖,例如,绿色,然后,无论我设置什么,如果我写:MyLabel.IsEnabled = False,文字将变为红色。

这项技术效果很好。 (即:xaml中的这一行将输出一个红色文本:<Label Foreground="Green" IsEnabled="False" />)。它与所有其他控件的工作方式相同。

但是当尝试使用textBox重现它时,它根本不起作用。

这是我的代码:

    <Style TargetType="TextBox">
        <Setter Property="Foreground" Value="Blue"/>

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TextBox">
                    <Grid>
                        <Border Name="Border">
                            <ScrollViewer x:Name="PART_ContentHost" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="PART_ContentHost" Property="Foreground" Value="Red"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

我尝试在PART_ContentHost上添加Foreground="{TemplateBinding Foreground}"但没有成功。

我怀疑这与PART_ContentHost是一个滚动查看器并且存在某种隐藏(至少来自我)继承的事实有关。

我能找到的唯一其他解释是TextBox类有一些特殊的处理方法,硬编码控件本身和它的PART_ContentHost部分之间的链接(绑定或​​propertychanged事件或其他什么?)

如果有人可以向我解释,这将是伟大的! 如果有人甚至可以提供一个很好的解决方案(一个不涉及讨厌的黑客,就像我现在使用的那个,但不会在这里显示,以免对读者造成严重的眼睛伤害),这将更大!

1 个答案:

答案 0 :(得分:4)

默认情况下,ScrollViewer本身的模板看起来像这样:

<ControlTemplate x:Key="ScrollViewerControlTemplate1" TargetType="{x:Type ScrollViewer}">
    <Grid x:Name="Grid" Background="{TemplateBinding Background}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/>
        <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
        <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
        <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
    </Grid>
</ControlTemplate>

顺便说一句,我通过使用Blend从TextBox中获取了它。

我敢打赌,如果您将触发器添加到该模板中的ScrollContentPresenter,那么您可以将其添加到标签中的ContentPresenter,以便它适合您。