模板遗留问题

 五、寻找失落的控件

   在寻找之前我们要先了解一些知识。在ControlTemplate里面有个Target,明确指出了它的树根。那么DataTemplate里面通常有很多控件,他的根目标是不是也是具有DataTemplate的控件呢?总的来说是,但实际是一个ContentPresenter或者ItemsPresenter。我们利用WPF Inspector工具来查看一下我们第一个使用DataTemplate例子中使用可视树,查询结果如图11:

图11

   这个给我们了很大的方便,如果我们想找模板中的控件的话,我们就可以先找到这个类的控件,然后在去遍历此控件的子控件。由于WPF数据驱动的缘故,如果我们去获得逻辑数据的话,通常情况可以从绑定的源去取,不必去目标的属性去取。 如TextBox1的数据为源,TextBox2为目标,把第二个TextBox的值绑定在第一个TextBox上面,我们不需要去找TextBox2,可以直接找TextBox1的依赖性属性的数据的来源去取。但是如果要获取TextBox的Width还还必须要从TextBox去取的。好了下面就看一下怎么查找DataTemplate和ControlTemplate里面的控件。先看一个ControlTemplate的例子:

XAML
<Window x:Class="Template.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="300">
    <Window.Resources>
        <ControlTemplate x:Key="cTmp">
            <StackPanel Background="Orange">
                <TextBox x:Name="textBox1" Margin="6"></TextBox>
                <TextBox x:Name="textBox2" Margin="6"></TextBox>
                <TextBox x:Name="textBox3" Margin="6"></TextBox>
            </StackPanel>
        </ControlTemplate>
    </Window.Resources>
    <StackPanel>
        <UserControl x:Name="uc" Template="{StaticResource cTmp}" Margin="5"/>
        <Button Content="找控件" Width="120" Height="30" Click="Button_Click"/>
    </StackPanel>
</Window>

其对应的可视树为图12;

图12

   我们可以通过目标控件的 TextBox tb = this.uc.Template.FindName("textBox1", this.uc) as TextBox;找到其中的一个TextBox控件,然后找其父类控件,最后再找其他的子控件。下面给出button按钮单击事件的代码:

cs
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            TextBox tb = this.uc.Template.FindName("textBox1", this.uc) as TextBox;
            tb.Text = "hello wpf";
            StackPanel sp = tb.Parent as StackPanel;
            (sp.Children[1] as TextBox).Text = "111";
            (sp.Children[2] as TextBox).Text = "222";

        }

  下面接着演示一个DataTemplate里面的控件。给出一个ListView控件里面放的有GridView,在GridView里面通过CellTemplate(里面嵌套的是TextBox或者是其他控件)来绑定网格的内容。当点击TextBox时,获取相同行的其他控件的值。下面先给出代码,然后用工具给出可视树的图,然后用代码获取:

XAML
<Window x:Class="WpfControlTemlate.FindControls"
        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:WpfControlTemlate"
        Title="FindControls" Height="300" Width="300" Background="Orange">
    <Window.Resources>
        <c:ArrayList x:Key="stuList">
            <local:Student ID="1" Name="haiziguo" Skill="WPF" HasJob="False"/>
            <local:Student ID="2" Name="shanjige" Skill="C++" HasJob="True"/>
            <local:Student ID="3" Name="xiaozhang" Skill="C#" HasJob="False"/>
            <local:Student ID="3" Name="chenwenzi" Skill="Test" 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="hjDT">
            <CheckBox x:Name="checkBoxJob" IsChecked="{Binding HasJob}"/>
        </DataTemplate>
    </Window.Resources>
    <Grid Margin="5">
        <ListView x:Name="listViewStudent" ItemsSource="{StaticResource stuList}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}"/>
                    <GridViewColumn Header="姓名" CellTemplate="{StaticResource nameDT}"/>
                    <GridViewColumn Header="技术" CellTemplate="{StaticResource skillDT}"/>
                    <GridViewColumn Header="已工作" CellTemplate="{StaticResource hjDT}"/>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

可视树为图13:

图13

后台代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfControlTemlate
{
    /// <summary>
    /// FindControls.xaml 的交互逻辑
    /// </summary>
    public partial class FindControls : Window
    {
        public FindControls()
        {
            InitializeComponent();
        }

        private void textBoxName_GotFocus(object sender, RoutedEventArgs e)
        {
            TextBox tb = e.OriginalSource as TextBox;
            ContentPresenter cp = tb.TemplatedParent as ContentPresenter;
            Student stu = cp.Content as Student;
            this.listViewStudent.SelectedItem = stu;

            ListViewItem lvi = this.listViewStudent.ItemContainerGenerator.ContainerFromItem(stu) as ListViewItem;
            CheckBox chb = this.FindVisualChild<CheckBox>(lvi);
            MessageBox.Show(chb.IsChecked.ToString());
        }

        //下面是一个递归算法
        private ChildType FindVisualChild<ChildType>(DependencyObject obj)
            where ChildType : DependencyObject
        //关于where可以参考 http://technet.microsoft.com/zh-cn/bb384067.aspx
        {
            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;
        }
    }
    #region Student——学生类
    public class Student
    {
        public string Name { get; set; }
        public int ID { get; set; }
        public string Skill { get; set; }
        public bool HasJob{ get; set; }             
    }
    #endregion
}

有个不理解的是ContentPresenter的Content

 

 

posted @ 2012-10-01 17:46  haiziguo  阅读(728)  评论(1编辑  收藏  举报