“井水不犯河水”常用来形容两个组织之间界限分明、互不相干,LogicTree与控件内部这颗小树之间就保持着这种关系。换句话说,如果UI元素树上有个X:Name=“TextBox1”的控件,某个控件内部也是由Template生成的x:Name="TextBox1"的控件,它们并不冲突,LogicTree不会看到控件内部的细节,控件内部元素也不会去理会控件外面是什么值。你可能会想:“这样一来,,万一我想从控件外部访问内部的控件,获取它的属性值,岂不是做不到了。”放心,WPF为我们准备了访问控件内部小世界的入口,现在我们就开始出发寻找那些失落的控件。
由ControlTemplate和DataTemplate生成的控件都是“由Template生成的控件”。ControlTemplate和DataTemplate两个类均派生自FrameWorkTemplate类,这个类有个名为FindName的方法供我们检索其内部控件。也就是说,只要我们能拿到Template,找到其内部控件就不成问题。对于ControlTemplate对象,访问其目标控件的Template属性就可以拿到,但想拿到DataTemplate就要费一番周折了。千万不要以为ListBoxItem或者ComBoxItem容器就是DataTemplate的目标控件哦!因为控件的Template和ContentTemplate完全是两码事。
我们先来寻找由ControlTemplate生成的控件。首先设计一个ControlTemplate并把它应用在一个UserControl控件上。界面上还有一个Button,在它的Click事件处理器中我们检索ControlTemplate生成的代码。
程序的XAML代码如下:
[html]
<Window x:Class="WpfApplication11.wnd11431"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="wnd11431" Height="174" Width="300">
<Window.Resources>
<ControlTemplate x:Key="cTemp">
<StackPanel>
<TextBox x:Name="txtBox1" BorderBrush="Black" Margin="5"></TextBox>
<TextBox x:Name="txtBox2" BorderBrush="Black" Margin="5"></TextBox>
<TextBox x:Name="txtBox3" BorderBrush="Black" Margin="5"></TextBox>
</StackPanel>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<UserControl x:Name="uc" Template="{StaticResource cTemp}" Margin="5"></UserControl>
<Button Content="Find By Name" Width="200" Click="Button_Click"></Button>
</StackPanel>
</Window>
Button的事件处理器代码如下:
[csharp]
private void Button_Click(object sender, RoutedEventArgs e)
{
TextBox tb = uc.Template.FindName("txtBox1", uc) as TextBox;
tb.Text = "TextBox1";
StackPanel sp = tb.Parent as StackPanel;
(sp.Children[1] as TextBox).Text = "TextBox2";
(sp.Children[2] as TextBox).Text = "TextBox3";