2

我的问题有点类似于这个: 我的 TextBox 控件模板有问题

但我想更进一步:

我的问题很简单:我有模板化控件(标签、文本框、复选框等......)。每个控件都有默认值,可以通过设置控件实例的属性值在运行时全部覆盖。而且无论为属性设置什么值,我决定在 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>

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

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

但是当试图用文本框重现它时,它根本不起作用。

这是我的代码:

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

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

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

我能找到的唯一其他解释是 TextBox 类具有某种特殊处理,可以硬编码控件本身与其 PART_ContentHost 部分之间的链接(绑定或​​ propertychanged 事件或其他?)

如果有人可以向我解释这一点,那就太好了!如果有人甚至可以提供一个很好的解决方案(一个不涉及像我目前使用的那样令人讨厌的黑客攻击但不会在此处显示以免对读者造成严重眼部伤害的解决方案),这将是更大的!

4

1 回答 1

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在标签中所做的那样,它将为您工作。

于 2011-06-01T14:10:58.827 回答