WPF Template模版之寻找失落的控件【三】

时间:2022-06-01 16:41:28

“井水不犯河水”常用来形容两个组织之间界限分明、互不相干,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";