模板

DataTemplate数据的外衣

就相当于一个控件,里面可以自定义各格数据展示格式,然后使用控件的ItemTemplate、ContentTemplate、GridViewColumn(单元格)属性来关联此模板

<Window x:Class="WpfApplication2.template"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:WpfApplication2"

        mc:Ignorable="d"

        Title="template" Height="320.69" Width="492.241">

    <Window.Resources>

        <!--定义给ListBox使用的DataTemplate-->

        <DataTemplate x:Key="lb">

            <StackPanel  Orientation="Horizontal">

                <Label x:Name="label" Content="{Binding Name}"    />

                <Label x:Name="label2" Content="{Binding Sex}"  />

            </StackPanel>

        </DataTemplate>

        <!--定义给UserControl使用的DataTemplate-->

        <DataTemplate x:Key="show">

            <StackPanel  Orientation="Horizontal">

                <Label x:Name="name" Content="{Binding Name}"    />

                 <Label x:Name="sex" Content="{Binding Sex}"    />

            </StackPanel>

        </DataTemplate>

    </Window.Resources>

    <Grid>

        <!--一般使用控件的ItemTemplate、ContentTemplate、GridViewColumn(单元格)来关联模板-->

        <ListBox x:Name="listBox"  ItemTemplate="{StaticResource lb}" />

        <UserControl x:Name="uc" ContentTemplate="{StaticResource show}" Content="{Binding Path=SelectedItem,ElementName=listBox}">

        </UserControl>

    </Grid>

</Window>

当然也可这样写

<ListBox x:Name="listBox"  >

            <ListBox.ItemTemplate>

                <DataTemplate  >

                    <StackPanel  Orientation="Horizontal">

                        <Label x:Name="label" Content="{Binding Name}"    />

                        <Label x:Name="label2" Content="{Binding Sex}"  />

                    </StackPanel>

                </DataTemplate>

            </ListBox.ItemTemplate>

    </ListBox>

后台

   public partial class template : Window

    {

        public template()

        {

            InitializeComponent();

            var list = new List<Human2>() {

                new Human2() { Name="刘德华", Sex="88"},

                 new Human2() { Name="刘德华2", Sex="89"},

                  new Human2() { Name="刘德华3", Sex="90"},

            };

            listBox.ItemsSource = list;

        }

    } 

    public class Human2

    {

        public string Name { get; set; }

        public string Sex { get; set; }

    }

ControlTemplate控件的外衣

相当于CSS样式,可通过Blend软件快速打碎一个控件,然后可以自己根据需求进行调整里面的小控件,调整完后就相当于一个样式,最终附加给控件上即可。

 

设计好样式后,这样应用

   <TextBox x:Name="textBox" Style="{DynamicResource TextBoxStyle1(这里是样式名称)}"/>

ControlTemplate里的控件可以使用TemplateBinding将自己的属性值关联在目标控件的某个属性上,如下图

ItemsControl的PanelTemplate

条目类型的控件都有一个ItemsControl属性,可以像下图使用来改变方向等。相当于用这个模板来包含着里面的项

 

 

DataTemplate与ControlTemplate应用

DataTemplate的树根是ContentPresenter控件,可以通过其TemplateParent获取,此属性不为null则说是由模板生成的。

其实DataTemplate里面在使用{Bingding XX}没有使用指定Source,是因为不指定Source时是一层一层向上查找DataContext属性。

如果想把ControlTemmplate(样式)应用到一种类型控件上,可以这样写(不指定x:Key属性即可):

 <Style  TargetType="{x:Type TextBox}">

同理,DataTemplate也可以指定某一种类型数据上(不需要x:key,只指定DataType属性到某类型上):

  <DataTemplate DataType="{x:Type local:Student7}">

那么,如果某控件的DataSource绑定的数据类型是Student7的话会自动默认使用上面的模板

如果Bingding源为xml(绑定法可见bingding章节),则DataType=“绑定的Path”,例如xml的结构层次为“StudentList/Student”,那么DataType=“Student”也是可以的,下面举个绑定树结构控件为例

 

只不过例子是使用了TreeView特有的绑定模板HierarchicalDataTemplate ,原理一样的

<Window.Resources>

        <XmlDataProvider  x:Key="ds" Source="bj.xml" XPath="Data/Grade"></XmlDataProvider>

        

        <!--年级模板-->

        <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">

            <TextBlock Text="{Binding XPath=@Name}" />

        </HierarchicalDataTemplate>

        <!--班级模板-->

        <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">

            <RadioButton Content="{Binding XPath=@Name}" GroupName="gn"></RadioButton>

        </HierarchicalDataTemplate>

        <!--组模板-->

        <HierarchicalDataTemplate DataType="Group" >

            <CheckBox  Content="{Binding XPath=@Name}"></CheckBox>

        </HierarchicalDataTemplate>

    </Window.Resources>

    <Grid>

        <TreeView x:Name="treeView"   ItemsSource="{Binding Source={StaticResource ds}}"/>

    </Grid>

  

 

当换成Menu控件时还可以在点击时获取其XMl对象

<Window.Resources>

        <XmlDataProvider  x:Key="ds" Source="bj.xml" XPath="Data/Grade"></XmlDataProvider>

        

        <!--年级模板-->

        <HierarchicalDataTemplate DataType="Grade" ItemsSource="{Binding XPath=Class}">

            <Grid>

                <TextBlock Text="{Binding XPath=@Name}"   /> 

            </Grid>

            

        </HierarchicalDataTemplate>

        <!--班级模板-->

        <HierarchicalDataTemplate DataType="Class" ItemsSource="{Binding XPath=Group}">

            <RadioButton Content="{Binding XPath=@Name}" GroupName="gn"></RadioButton>

        </HierarchicalDataTemplate>

        <!--组模板-->

        <HierarchicalDataTemplate DataType="Group" >

            <TextBlock Text="{Binding XPath=@Name}"   />

        </HierarchicalDataTemplate>

    </Window.Resources>

    <Grid>

        <StackPanel MenuItem.Click="StackPanel_Click">

        <Menu x:Name="treeView"   ItemsSource="{Binding Source={StaticResource ds}}"/>

        </StackPanel> 

    </Grid>

    private void StackPanel_Click(object sender, RoutedEventArgs e)

        {

            MenuItem mi = e.OriginalSource as MenuItem;

            XmlElement ex = mi.Header as XmlElement;

            MessageBox.Show(ex.Attributes["Name"].Value.ToString());

        }

bj.xml文件内容

<?xml version="1.0" encoding="utf-8" ?>

<Data xmlns="">

  <Grade Name="一年级">

    <Class Name="甲班">

      <Group Name="A组"></Group>

      <Group Name="B组"></Group>

    </Class>

    <Class Name="乙班">

      <Group Name="A组"></Group>

      <Group Name="B组"></Group>

    </Class>

  </Grade>

  <Grade Name="二年级">

    <Class Name="甲班">

      <Group Name="A组"></Group>

      <Group Name="B组"></Group>

    </Class>

  </Grade>

</Data>

查找控件

ControlTemplate与DataTemplate都是由Template生成的控件,派生自FrameworkTemplate;

查找ControlTemplate里面的控件

 <Window.Resources>

        <ControlTemplate x:Key="ct">

            <StackPanel x:Name="sp">

                <TextBox x:Name="tb1"></TextBox>

                <TextBox x:Name="tb2"></TextBox>

                <Button x:Name="button" Content="Button"/>

            </StackPanel>

        </ControlTemplate>

    </Window.Resources>

    <Grid>

        <UserControl Template="{StaticResource ct}" x:Name="uc" Loaded="uc_Loaded"></UserControl>

    </Grid>
    private void uc_Loaded(object sender, RoutedEventArgs e)

        {

            var tb = uc.Template.FindName("tb1", uc) as TextBox;

            tb.Text = "就是我";

        }

查找DataTemplate里面的控件

<Window.Resources>

        <local:Student x:Key="st" Name="姓名1" Age="100"></local:Student>

        <DataTemplate x:Key="dt">

            <StackPanel x:Name="sp">

                <TextBox x:Name="tb1" Text="{Binding Name}"></TextBox>

                <TextBox x:Name="tb2"  Text="{Binding Age}"></TextBox>

                <Button x:Name="button" Content="Button" Click="button_Click"/>

            </StackPanel>

        </DataTemplate>

    </Window.Resources>

    <Grid>

        <ContentPresenter x:Name="cp" ContentTemplate="{StaticResource dt}" Content="{StaticResource st}"

        </ContentPresenter>

    </Grid>

     private void button_Click(object sender, RoutedEventArgs e)

        { 

 //这仅是获取控件的方法

            var tb = cp.ContentTemplate.FindName("tb1", cp) as TextBox;

            MessageBox.Show(tb.Text);

        }

        private void button_Click(object sender, RoutedEventArgs e)

        {

            //这是获取业务数据的方法

            var bt = e.OriginalSource as Button;

            //不管DataTemplate作为哪个控件的模板,触发此事件的控件多深,都可以通过TemplatedParent属性直接获取ContentPresenter

            var cp = bt.TemplatedParent as ContentPresenter;

            var student = cp.Content as Student;

            MessageBox.Show(student.Name);

        }

原文地址:https://www.cnblogs.com/evemen/p/6239341.html