DataTemplate 和 ControlTemplate 两个类均派生自 FrameWorkTemplate类。这个类有个 FindName方法 供我们查询内部控件。

        ControlTemplate 对象: 访问其目标控件 Template . FindName就能拿到。

        DataTemplate 对象:     直接使用低层数据(如果想获得控件长度、宽度 Template . FindName)。

 

1、获得ControlTemplate 中的控件。

效果:


 

<Window x:Class="AutomaticConfigurationAPP.Window5"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window5" Height="300" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="cTmp">
            <StackPanel Background="Orange">
               <TextBox x:Name="textbox1" Margin="6"/>
                <TextBox x:Name="textbox2" Margin="6,0"/>
                <TextBox x:Name="textbox3" Margin="6"/>
            </StackPanel>
        </ControlTemplate>
    </Window.Resources>
    <StackPanel Background="Yellow">
        <UserControl x:Name="uc" Template="{StaticResource cTmp}" Margin="5"/>
        <Button Content="FindName" Click="Button_Click"/>
    </StackPanel>
</Window>

事件

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //Template.FindName
            TextBox tb= uc.Template.FindName("textbox1", this.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";
        }

 

2、获得DataTemplate 中的控件。

     如果获得与用户界面相关的数据(比如控件的宽度、高度)ContentTemplate.FindName("")。

     如果获得与业务相关的数据,直接访问底层(WPF采用数据驱动UI逻辑)Content

效果:

 

 

 

[csharp] view plain copy
 
  1. public class Student  
  2. {  
  3.     public int Id { get; set; }  
  4.     public string Name { get; set; }  
  5.     public string Skill { get; set; }  
  6.     public bool HasJob { get; set; }  
  7. }  


XAML

 

<Window x:Class="AutomaticConfigurationAPP.Window6"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:AutomaticConfigurationAPP"
        Title="Window6" Height="300" Width="300">
    <Window.Resources>
        <local:Student x:Key="stu" Id="1" Name="姓名" Skill="wpf" HasJob="True"/>
        
        <DataTemplate x:Key="stuDT">

            <Border BorderBrush="Orange" BorderThickness="2" CornerRadius="5">
                <StackPanel>
                    <TextBlock Text="{Binding Id}" Margin="5"/>
                    <TextBlock x:Name="textblockname" Text="{Binding Name}" Margin="5"/>
                    <TextBlock Text="{Binding Skill}" Margin="5"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <StackPanel>
        <ContentPresenter x:Name="cp" 
                          Content="{StaticResource stu}" 
                          ContentTemplate="{StaticResource stuDT}"

                          Margin="5"/>
        <!--Content="{StaticResource 内容数据源}" ContentTemplate="{StaticResource 内容模板}"-->
        <Button Content="Find" Margin="5,0" Click="Button_Click"/>
    </StackPanel>
</Window>

 

C#

           //内容模板查找控件
           TextBlock tb= this.cp.ContentTemplate.FindName("textblockname", this.cp) as TextBlock;  //CP就是一个contentpresenter
           MessageBox.Show(tb.Text);


           //直接使用底层数据
           Student stu = this.cp.Content as Student;
           MessageBox.Show(stu.Name);

 

 

实例:访问业务逻辑数据、访问界面逻辑数据

界面:

 

XAML

 

<Window x:Class="AutomaticConfigurationAPP.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
        xmlns:local="clr-namespace:AutomaticConfigurationAPP"

        Title="Window2" Height="300" Width="300">
    <Window.Resources>
        <c:ArrayList x:Key="stuList">
            <local:Student Id="1" Name="a" Skill="wpf" HasJob="True"/>
            <local:Student Id="2" Name="b" Skill="MVC" HasJob="True"/>
            <local:Student Id="3" Name="c" Skill="c#" HasJob="True"/>
        </c:ArrayList>
        <DataTemplate x:Key="nameDT">
            <TextBox x:Name="textboxname" Text="{Binding Name}" GotFocus="textboxname_GotFocus"/>
        </DataTemplate>
        <DataTemplate x:Key="skillDT">
            <TextBox x:Name="textboxskill" Text="{Binding Skill}"/>
        </DataTemplate>
        <DataTemplate x:Key="hasjobDT">
            <CheckBox x:Name="checkboxJob" IsChecked="{Binding HasJob}"/>
        </DataTemplate>
    </Window.Resources>
    <Grid Margin="5">
        <ListView x:Name="listviewStudent" ItemsSource="{StaticResource stuList}">
            <ListView.View>


                <!--ListView的View属性是GridView-->
                <GridView>
                    <GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}"/>
                    <!--CellTemplate是TextBox-->
                    <GridViewColumn Header="姓名" CellTemplate="{StaticResource nameDT}"/>
                    <GridViewColumn Header="技能" CellTemplate="{StaticResource skillDT}"/>
                    <GridViewColumn Header="已工作" CellTemplate="{StaticResource hasjobDT}"/>
                </GridView>
                
            </ListView.View>
        </ListView>


    </Grid>
</Window>

 

c#

        private void textboxname_GotFocus(object sender, RoutedEventArgs e)
        {
            //访问业务逻辑数据
            TextBox tb = e.OriginalSource as TextBox;//获得事件的源头(TextBox)
            //沿UI元素树上溯到DataTemplate的目标控件(ContentPresenter),并获取它内容,它内容一定是个Student
            ContentPresenter cp = tb.TemplatedParent as ContentPresenter;
            Student stu = cp.Content as Student;//一行
            //MessageBox.Show(stu.HasJob.ToString());
            this.listviewStudent.SelectedItem = stu;


            //访问界面逻辑数据
            //查找包含的ListViewItem
            ListViewItem lvi = this.listviewStudent.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;
            CheckBox chb = this.FindVisualChild<CheckBox>(lvi);
            MessageBox.Show(chb.Name);


        }


        private ChildType FindVisualChild<ChildType>(DependencyObject obj)
            where ChildType:DependencyObject
        {
            //可视化对象包含的子集个数
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                //返回指定父可视对象中位于指定集合索引位置的子可视对象
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is ChildType)
                {
                    return child as ChildType;
                }
                else
                {
                    ChildType childofChild = FindVisualChild<ChildType>(child);
                    if (childofChild != null)
                        return childofChild;
                }
            }
            return null;
        }