模板
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);
}