为一个文本框自定义模板,因为我想上的IsEnabled = FALSE
我的问题不表现有点类似于此: 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事件或别的东西吗?)
如果有人可以向我解释这一点,这将是伟大的! 如果有人甚至可以提供一个很好的解决方案(不涉及像我目前正在使用的一个讨厌的黑客攻击,但不会在这里显示,以免对读者造成重大伤害),这将会是平坦的更大!
默认情况下,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
,以便它可以为您工作。
对我有意义。 ContentPresenter位于ScrollViewer内部,所以'Foreground = Green'在'Foreground = Red'的控件内。它们是两个独立的属性,所以可视化树最远的一个被应用。在标签的情况下,您正在修改完全相同的属性,以便最后应用的属性(触发器中的那个属性)生效。 – Rachel 2011-06-01 16:16:03
没关系,所以我测试了一下,可以确认这个作品。详细阐述这个主题,我认为这是实际的预期,因为scrollViewer不会将继承的属性传播到其可视化树中。所以令人困惑的部分是,具有contentPresenter或TextBlock作为controlPresenter的控件将传播它,但具有作为ControlPresenter的ScrollViewer的控件不会导致此行为。谢谢你的头 – David 2011-06-14 09:55:09