该控件叫Summary, 主要是一些汇总信息的显示,有几个地方用,之前都是分散到各个XAML 文件里,不统一。
本人WPF新手,对XAML了解不多,做这个软件基本上都是用CM,界面布局用AvalonDock。
由于缺乏相关经验,又没有一个能问得上的人指导,写这个控件费了我很长时间(啥时有空啥时动动)。
之前主要做一些功能方面的,没有心思美化界面,现在虽然还有很多功能没写,但是基本上够自己用了,放下心思来做一些界面上的东西,要不然何苦选择WPF?先看一下图:该CustomControl 由4部分组成:大标题,小标题,值及Detail。
虽然细分这么多,但实质上还是一个列表类的控件,所以选择继承自ItemsControl.做这个控件的时候,遇到了一些详细的问题不知道怎么解决,Google/Bing 都没有找到我要了解的,Baidu 更不用提了,漫天的转载,Copy.1, 类似ComboBox 的DisplayMemberPath 如何弄?既然都自定控件了,当然是想让它适用不同场景,不能局限于某一个实体类,最好是能像DisplayMemberPath ValueMemberPath 这样的属性。
这里,我定义了:ItemTitlePathProperty 及ItemValuePathProperty 来处理。
2,有了上面两个依赖属性,但是还不足以处理更多的场景,最好是能有不同的Template 。
这里我定义了:TitleTemplate / ValueTemplate及DetailTemplate.第一个问题,只需定义一个简单的DataTemplate ,然后用TemplateBinding 即可做到。
但是要和第二个问题结合在一起,就牵扯到模板切换及数据切换的问题,因为第一问题所用的数据被指定为某实体类的某个属性,第二个问题的数据要指定为整个实体。
解决第一个问题,需要重写PrepareContainerForItemOverride 方法,第二个需要重写OnApplyTemplate不多说了,怕误导大家,毕竟,我懂的不多,上代码,供参考:模板文件:1<ResourceDictionaryxmlns="/winfx/2006/xaml/presentation"2xmlns:x="/winfx/2006/xaml"3xmlns:local="clr-namespace:AsNum.WPF.Controls"4>567<DataTemplate x:Key="SummaryTitleTemplate">8<TextBlock Text="{Binding}" Foreground="White"/>9</DataTemplate>1011<DataTemplate x:Key="SummaryValueTemplate">12<Border HorizontalAlignment="Right" Background="#FF535C7B" CornerRadius="10">13<TextBlock Text="{Binding}" Padding="8,3"Foreground="White"/>14</Border>15</DataTemplate>161718<Style TargetType="{x:Type local:Summary}">19<Setter Property="Template">20<Setter.Value>21<ControlTemplate TargetType="{x:Type local:Summary}"> 22<Border Background="{TemplateBinding Background}"23BorderBrush="{TemplateBinding BorderBrush}"24BorderThickness="{TemplateBinding BorderThickness}"25>2627<StackPanel Height="auto">28<Border Padding="20,5"CornerRadius="5,5,0,0" Background="#10a8ab">29<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Typelocal:Summary}}, Path=Title}" FontSize="18.667" Foreground="White" HorizontalAlignment="Center"/>30</Border> 31<Border Background="#FF394165" CornerRadius="0,0,3,3" Padding="5">32<ItemsPresenter />33</Border>34</StackPanel>3536</Border>37</ControlTemplate>38</Setter.Value>39</Setter>40</Style>4142<Style TargetType="{x:Type local:SummaryItem}">43<Setter Property="Template">44<Setter.Value>45<ControlTemplate TargetType="{x:Typelocal:SummaryItem}">46<Border x:Name="Item"47Padding="3"48BorderBrush="{TemplateBinding BorderBrush}"49BorderThickness="{TemplateBinding BorderThickness}">505152<Border.Background>53<SolidColorBrush />54</Border.Background>5556<StackPanel>57<DockPanel>58<ContentControl x:Name="PART_Title" 59Content="{TemplateBinding Title}"60ContentTemplate="{StaticResource SummaryTitleTemplate}"61/>6263<ContentControlx:Name="PART_Value"64Content="{TemplateBinding Value}"65ContentTemplate="{StaticResource SummaryValueTemplate}"66Width="auto"67DockPanel.Dock="Right"68HorizontalAlignment="Right"69/>7071</DockPanel>72<ContentControl Margin="0,2,0,2"x:Name="PART_Detail" ContentTemplate="{TemplateBinding DetailTemplate}"/> 73</StackPanel>7475<Border.Triggers>76<EventTriggerRoutedEvent="Border.MouseEnter">77<BeginStoryboard>78<Storyboard>79<ColorAnimationTo="#FF535C7B" Duration="0:0:1"80Storyboard.TargetName="Item"81Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/>82</Storyboard>83</BeginStoryboard>84</EventTrigger>85<EventTriggerRoutedEvent="Border.MouseLeave">86<BeginStoryboard>87<Storyboard>88<ColorAnimationTo="Transparent" Duration="0:0:1"89Storyboard.TargetName="Item"90Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"/> 91</Storyboard>92</BeginStoryboard>93</EventTrigger>94</Border.Triggers>959697</Border>98</ControlTemplate>99</Setter.Value>100</Setter>101</Style>102103</ResourceDictionary>Summary.cs1using System;2using System.Collections.Generic;3using System.Collections.ObjectModel;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7using System.Windows;8using System.Windows.Controls;9using System.Windows.Data;10using System.Windows.Documents;11using System.Windows.Input;12using System.Windows.Media;13using System.Windows.Media.Imaging;14using System.Windows.Navigation;15using System.Windows.Shapes;1617namespace AsNum.WPF.Controls {18public class Summary : ItemsControl {192021public static DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(Summary));2223public static DependencyProperty ItemTitlePathProperty = DependencyProperty.Register("ItemTitlePath", typeof(string), typeof(Summary)); 2425public static DependencyProperty ItemValuePathProperty = DependencyProperty.Register("ItemValuePath", typeof(string), typeof(Summary)); 2627public static DependencyProperty ItemDetailTemplateProperty = DependencyProperty.Register("ItemDetailTemplate", typeof(DataTemplate), typeof(Summary));2829public static DependencyProperty ItemTitleTemplateProperty = DependencyProperty.Register("ItemTitleTemplate", typeof(DataTemplate), typeof(Summary));3031public static DependencyProperty ItemValueTemplateProperty = DependencyProperty.Register("ItemValueTemplate", typeof(DataTemplate), typeof(Summary));3233public string Title {34get {35return (string)this.GetValue(TitleProperty);36}37set {38this.SetValue(TitleProperty, value);39}40}4142public string ItemTitlePath {43get {44return (string)this.GetValue(ItemTitlePathProperty); 45}46set {47this.SetValue(ItemTitlePathProperty, value);48}49}5051public string ItemValuePath {52get {53return (string)this.GetValue(ItemValuePathProperty); 54}55set {56this.SetValue(ItemValuePathProperty, value);57}58}5960public DataTemplate ItemDetailTemplate {61get {62return(DataTemplate)this.GetValue(ItemDetailTemplateProperty);63}64set {65this.SetValue(ItemDetailTemplateProperty, value);66}67}6869public DataTemplate ItemTitleTemplate {70get {71return(DataTemplate)this.GetValue(ItemTitleTemplateProperty);72}73set {74this.SetValue(ItemTitleTemplateProperty, value);75}76}7778public DataTemplate ItemValueTemplate {79get {80return(DataTemplate)this.GetValue(ItemValueTemplateProperty);81}82set {83this.SetValue(ItemValueTemplateProperty, value);84}85}8687static Summary() {88DefaultStyleKeyProperty.OverrideMetadata(typeof(Summary), new FrameworkPropertyMetadata(typeof(Summary)));89}9091protected override voidPrepareContainerForItemOverride(DependencyObject element, object item) {92base.PrepareContainerForItemOverride(element, item);93var ele = element as SummaryItem;9495{96Binding binding = new Binding();97ele.SetBinding(SummaryItem.ItemProperty, binding);98}99100if (!string.IsNullOrEmpty(this.ItemTitlePath)) {101Binding binding = new Binding(this.ItemTitlePath);102ele.SetBinding(SummaryItem.TitleProperty, binding); 103}104105if (!string.IsNullOrEmpty(this.ItemValuePath)) {106Binding binding = new Binding(this.ItemValuePath);107ele.SetBinding(SummaryItem.ValueProperty, binding); 108}109110ele.DetailTemplate = this.ItemDetailTemplate;111ele.TitleTemplate = this.ItemTitleTemplate;112ele.ValueTemplate = this.ItemValueTemplate;113}114115protected override DependencyObject GetContainerForItemOverride() {116return new SummaryItem();117}118119}120 }SummaryItem.cs1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;6using System.Windows;7using System.Windows.Controls;8using System.Windows.Data;9using System.Windows.Documents;10using System.Windows.Input;11using System.Windows.Media;12using System.Windows.Media.Imaging;13using System.Windows.Navigation;14using System.Windows.Shapes;1516namespace AsNum.WPF.Controls {1718[TemplatePart(Name = "PART_Value", Type=typeof(ContentControl))] 19[TemplatePart(Name = "PART_Title", Type = typeof(ContentControl))] 20[TemplatePart(Name = "PART_Detail", Type = typeof(ContentControl))] 21public class SummaryItem : Control {2223public static DependencyProperty ItemProperty = DependencyProperty.Register("Item", typeof(object), typeof(Summary));24public static DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(SummaryItem));25public static DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(SummaryItem));26public static DependencyProperty DetailTemplateProperty = DependencyProperty.Register("DetailTemplate", typeof(DataTemplate),typeof(SummaryItem));27public static DependencyProperty TitleTemplateProperty = DependencyProperty.Register("TitleTemplate", typeof(DataTemplate),typeof(SummaryItem));28public static DependencyProperty ValueTemplateProperty = DependencyProperty.Register("ValueTemplate", typeof(DataTemplate),typeof(SummaryItem));2930public object Item {31get {32return (object)this.GetValue(ItemProperty);33}34set {35this.SetValue(ItemProperty, value);36}37}38public string Title {39get {40return (string)this.GetValue(TitleProperty);41}42set {43this.SetValue(TitleProperty, value);44}45}4647public object Value {48get {49return this.GetValue(ValueProperty);50}51set {52this.SetValue(ValueProperty, value);53}54}5556public DataTemplate DetailTemplate {57get {58return(DataTemplate)this.GetValue(DetailTemplateProperty);59}60set {61this.SetValue(DetailTemplateProperty, value);62}63}6465public DataTemplate TitleTemplate {66get {67return (DataTemplate)this.GetValue(TitleTemplateProperty); 68}69set {70this.SetValue(TitleTemplateProperty, value);71}72}7374public DataTemplate ValueTemplate {75get {76return(DataTemplate)this.GetValue(ValueTemplateProperty);77}78set {79this.SetValue(ValueTemplateProperty, value);80}81}8283static SummaryItem() {84DefaultStyleKeyProperty.OverrideMetadata(typeof(SummaryItem), new FrameworkPropertyMetadata(typeof(SummaryItem)));85}8687public override void OnApplyTemplate() {88base.OnApplyTemplate();8990var pv =(ContentControl)this.Template.FindName("PART_Value", this);91if (pv != null && this.ValueTemplate != null) {92pv.Content = this.Item;93pv.ContentTemplate = this.ValueTemplate;94}9596var pt = (ContentControl)this.Template.FindName("PART_Title", this);97if (pt != null && this.TitleTemplate != null) {98pt.Content = this.Item;99pt.ContentTemplate = this.TitleTemplate;100}101102var pd =(ContentControl)this.Template.FindName("PART_Detail", this);103if (pd != null && this.DetailTemplate != null) {104pd.Content = this.Item;105}106}107}108 }用法:1<ac:Summary Grid.Row="0" Title="用法" ItemsSource="{Binding Items2}" ItemTitlePath="Title2" ItemValuePath="Value"/>23<ac:Summary Grid.Row="2" Width="200"4Title="{Binding Title2}" ItemsSource="{BindingItems2}"5ItemTitlePath="Title2" ItemValuePath="Value">6<ac:Summary.ItemDetailTemplate>7<DataTemplate>8<TextBlock Text="{Binding Title2}"/>9</DataTemplate>10</ac:Summary.ItemDetailTemplate>1112<ac:Summary.ItemValueTemplate>13<DataTemplate>14<Button Content="{Binding Value}"/>15</DataTemplate>16</ac:Summary.ItemValueTemplate> 17</ac:Summary>还有一些小细节需要自行调整。