UserControl的XAML代码(非常简略)如下:
<UserControl x:Class="MyApp.CodeLookupBox" x:Name="MainControl">
<UserControl.Resources>
<!-- tons of DataTemplates and Styles, most notably the style that
contains the control template for the ComboBox -->
<UserControl.Resources>
<ComboBox x:Name="ComboBox"
Margin="0"
Style="{DynamicResource ComboBoxStyle1}"
VerticalAlignment="Top"
ItemTemplate="{StaticResource GridViewStyleTemplate}"/>
</UserControl>
这个控件里有很多后台代码,主要是我用来选择下拉列表中使用的模板等方面的依赖属性。
让我感到困扰的是可编辑文本框。我希望能够从用户控件的样式中设置它的背景笔刷 - 例如,当我在我的XAML中声明一个这样的用户控件时,它使用类似于以下的样式:
<Style TargetType="{x:Type local:CodeLookupBox}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsRequired}" Value="True">
<Setter Property="EditableTextBoxBackground" Value="{StaticResource RequiredFieldBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
我最开始只是设置了UserControl的背景色,但这只是设置了可编辑文本框后方的背景色。文本框本身仍然是白色的。
在ComboBox的模板内部,有一个样式控制着文本框:
<Style x:Key="ComboBoxEditableTextBox" TargetType="{x:Type TextBox}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="MinWidth" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer
x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
还有一个 TextBox (在 ComboBox 的控件模板中)它的本质不好:
<TextBox
x:Name="PART_EditableTextBox"
Margin="{TemplateBinding Padding}"
Style="{StaticResource ComboBoxEditableTextBox}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}"/>
现在,关于ComboBoxEditableTextBox样式,有一定的“人类不应该知道的事情”元素。那个ScrollViewer在里面做什么呢?我不知道。但是我可以告诉你,如果我注释掉设置TextBox的ControlTemplate部分的样式,会发生非常糟糕的事情。
我还知道这一点:如果我显式地将TextBox的Background刷子设置为样式的setter之一,什么都不会发生。如果我明确地在PART_EditableTextBox上设置背景,也不会发生任何事情。(我可以设置它的前景色或字体族,它们可以正常工作。)
但是,如果我明确设置那个ScrollViewer的背景为绿色,那么,哇,TextBox就变成了绿色。
好吧,那么TextBox忽略了自己的背景,并使用控件模板中的背景。实际上,严格来说,它也没有使用控件模板中的背景。当我设置ScrollViewer的背景时,周围有一个明显的边距,而不是颜色完全填充TextBox。但是,那个边距是白色的,而不是背景颜色。
除非我能弄清楚TextBox为什么忽略了它的背景,否则我必须接受调整ScrollViewer的事实。那么,我该如何让它从用户控件的EditableTextBoxBackground属性获取刷子呢?我已经将其作为依赖属性,并在更改时正确地引发PropertyChanged事件。我在神秘的ScrollViewer的XAML中像这样绑定它:
Background="{Binding ElementName=MainControl,
Path=EditableTextBoxBackground,
Converter={StaticResource DebuggingConverter}}"
我在调试转换器时设置了一个断点。当控件首次绘制时,它被触发两次。第一次,刷子的值为null。第二次,它是正确的值。如果我在我的UserControl的构造函数中设置属性,它可以工作。
所以这就是我知道的:我的UserControl的属性被正确设置了。TextBox样式上的绑定已经正确地绑定到了UserControl的属性上。TextBox控件模板中的ScrollViewer绑定到了正确的属性上。当属性更改时,属性引发PropertyChanged事件并推送值到ScrollViewer背景属性。
但是什么也没有发生。
所以我想问三个问题:1)为什么?2)那个ScrollViewer到底是做什么用的?我有些怀疑,但现在已经是凌晨一点了,很难表达我的想法。3)为什么Blend给我提供的控件模板与这里找到的更易理解的控件模板不同?
真的,任何帮助都将不胜感激。