2011-06-01 52 views
2

我的问题不表现有点类似于此: Having an issue with my TextBox control template为一个文本框自定义模板,因为我想上的IsEnabled = FALSE

,但我想去远一点:

我的问题很简单: 我有模板控件(标签,文本框,复选框等)。通过设置控件实例的属性值,每个控件的默认值都可以在运行时被覆盖。不管设置为属性的值是多少,当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" />)。它与所有其他控件的工作方式相同。

但是当试图用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是一个scrollviewer并且存在某种隐藏的(至少从我)继承的事实有关。

以外唯一的解释我能找到的是TextBox类具有某种特殊处理的是硬编码的控制本身及其PART_ContentHost部分之间的联系(绑定或PropertyChanged事件或别的东西吗?)

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

回答

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> 

我说出来的文本框通过使用混合,顺便说一句。

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

+0

对我有意义。 ContentPresenter位于ScrollViewer内部,所以'Foreground = Green'在'Foreground = Red'的控件内。它们是两个独立的属性,所以可视化树最远的一个被应用。在标签的情况下,您正在修改完全相同的属性,以便最后应用的属性(触发器中的那个属性)生效。 – Rachel 2011-06-01 16:16:03

+0

没关系,所以我测试了一下,可以确认这个作品。详细阐述这个主题,我认为这是实际的预期,因为scrollViewer不会将继承的属性传播到其可视化树中。所以令人困惑的部分是,具有contentPresenter或TextBlock作为controlPresenter的控件将传播它,但具有作为ControlPresenter的ScrollViewer的控件不会导致此行为。谢谢你的头 – David 2011-06-14 09:55:09