本章记录一个问题:关于WPF 中控件“PART_XXX”内置的特殊名称解析和说明
实现TextBox外观的修改,需要圆角矩形,代码如下:
<TextBox x:Name="lname" Width="200" Height="30" Margin="0,5" Padding="2,5" BorderBrush="Teal" BorderThickness="1">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >
<ScrollViewer/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
编译-运行后,发现TextBox是不可用的,鼠标无法点入输入框了;
这是因为在改写Style的时候对Template进行改写了,使用Border控制边框的圆角,ScrollViewer (属于内容控件的一种 继承自ContentControl),可以将超出这个控件的部分用滚动条来滑动展示TextBox控件内部在检索的时候就找不到PART_ContentHost这个元素。
WPF中很多控件有“PART_XXX”这样的内置的特殊名称,不能修改或者不写,如上面的“PART_Track”,若不写或者修改名称,会导致鼠标无法拖动滑块。或者“PART_HorizontalScrollBar”、“PART_VerticalScrollBar”,若不写会导致滑块能显示但是不起作用。
WPF宝典里面的说的,在创建无外观控件的那一个章节里面,就是控件样式与内部逻辑分开。意思就是:当我们创建一个控件样式的时候,里面的元素属性什么的肯定要与这个控件的内部属性进行绑定,当一个控件比较复杂的时候,所创建的绑定表达式就会很多。这个时候wpf就有另外一个功能就是在控件内部重写OnApplyTemplate()方法,这个方法继承自FrameworkElement类。就是在这个方法里面通过固定的元素名称检索模板里面的的控件,用代码进行绑定,而这个TextBox控件只有一个就是这个"PART_ContentHost",实际上就是换了一种方法绑定而已。
就像上面说那样,如果在检索的时候没有发现这个元素,就说明没有这个功能,所有重写TextBox模板的时候需要在内部容器里面加一个ScrollViewer控件,并给他命名 x:Name="PART_ContentHost",TextBox控件内部在检索的时候就找得到这个元素,从而做好了绑定。
比如ScrollViewer的“PART_ContentHost”名称,就是表示这个控件是用于装载TextBox的文本内容的,虽说它是表示用于装载TextBox的文本内容的,但PART_ContentHost不能作为TextBox的名称,并且经过测试,这个名称只能用于ScrollViewer或者Adorner、Decorator控件。
至于这个TextBox具体内部怎么做的,我想知道为啥要写这个名字就行了,会用就行。
修改成如下代码就正常了,实现所期望的功能。
<TextBox x:Name="lname" Width="200" Height="30" Margin="0,5" Padding="2,5" BorderBrush="Teal" BorderThickness="1">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" >
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
几个人所得见解,欢迎留言交流指正。