标签:default tor 定义 metadata div out 移除 sys 中间
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.ComponentModel; namespace ZdfFlatUI { public class TimelineItem : ContentControl { #region DependencyProperty #region IsFirstItem /// <summary> /// 获取或者设置该项在列表中是否是第一个 /// </summary> [Bindable(true), Description("获取或者设置该项在列表中是否是第一个")] public bool IsFirstItem { get { return (bool)GetValue(IsFirstItemProperty); } set { SetValue(IsFirstItemProperty, value); } } public static readonly DependencyProperty IsFirstItemProperty = DependencyProperty.Register("IsFirstItem", typeof(bool), typeof(TimelineItem), new PropertyMetadata(false)); #endregion #region IsMiddleItem /// <summary> /// 获取或者设置该项在列表中是否是中间的一个 /// </summary> [Bindable(true), Description("获取或者设置该项在列表中是否是中间的一个")] public bool IsMiddleItem { get { return (bool)GetValue(IsMiddleItemProperty); } set { SetValue(IsMiddleItemProperty, value); } } public static readonly DependencyProperty IsMiddleItemProperty = DependencyProperty.Register("IsMiddleItem", typeof(bool), typeof(TimelineItem), new PropertyMetadata(false)); #endregion #region IsLastItem /// <summary> /// 获取或者设置该项在列表中是否是最后一个 /// </summary> [Bindable(true), Description("获取或者设置该项在列表中是否是最后一个")] public bool IsLastItem { get { return (bool)GetValue(IsLastItemProperty); } set { SetValue(IsLastItemProperty, value); } } public static readonly DependencyProperty IsLastItemProperty = DependencyProperty.Register("IsLastItem", typeof(bool), typeof(TimelineItem), new PropertyMetadata(false)); #endregion #endregion #region Constructors static TimelineItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TimelineItem), new FrameworkPropertyMetadata(typeof(TimelineItem))); } #endregion } }
Timeline代码
1 using System; 2 using System.Collections.Generic; 3 using System.Collections.Specialized; 4 using System.Linq; 5 using System.Text; 6 using System.Windows; 7 using System.Windows.Controls; 8 using System.ComponentModel; 9 namespace ZdfFlatUI 10 { 11 /// <summary> 12 /// 时间轴 13 /// </summary> 14 /// <remarks>add by zhidanfeng 2017.5.29</remarks> 15 public class Timeline : ItemsControl 16 { 17 #region private fields 18 #endregion 19 #region DependencyProperty 20 #region FirstSlotTemplate 21 /// <summary> 22 /// 获取或者设置第一个时间轴点的样子 23 /// </summary> 24 [Bindable(true), Description("获取或者设置第一个时间轴点的样子")] 25 public DataTemplate FirstSlotTemplate 26 { 27 get { return (DataTemplate)GetValue(FirstSlotTemplateProperty); } 28 set { SetValue(FirstSlotTemplateProperty, value); } 29 } 30 31 public static readonly DependencyProperty FirstSlotTemplateProperty = 32 DependencyProperty.Register("FirstSlotTemplate", typeof(DataTemplate), typeof(Timeline)); 33 #endregion 34 #region MiddleSlotTemplate 35 /// <summary> 36 /// 获取或者设置中间的时间轴点的样子 37 /// </summary> 38 [Bindable(true), Description("获取或者设置中间的时间轴点的样子")] 39 public DataTemplate MiddleSlotTemplate 40 { 41 get { return (DataTemplate)GetValue(MiddleSlotTemplateProperty); } 42 set { SetValue(MiddleSlotTemplateProperty, value); } 43 } 44 45 public static readonly DependencyProperty MiddleSlotTemplateProperty = 46 DependencyProperty.Register("MiddleSlotTemplate", typeof(DataTemplate), typeof(Timeline)); 47 #endregion 48 #region LastItemTemplate 49 /// <summary> 50 /// 获取或者设置最后一个时间轴点的样子 51 /// </summary> 52 [Bindable(true), Description("获取或者设置最后一个时间轴点的样子")] 53 public DataTemplate LastSlotTemplate 54 { 55 get { return (DataTemplate)GetValue(LastSlotTemplateProperty); } 56 set { SetValue(LastSlotTemplateProperty, value); } 57 } 58 59 public static readonly DependencyProperty LastSlotTemplateProperty = 60 DependencyProperty.Register("LastSlotTemplate", typeof(DataTemplate), typeof(Timeline)); 61 #endregion 62 #region IsCustomEverySlot 63 /// <summary> 64 /// 获取或者设置是否自定义每一个时间轴点的外观。 65 /// </summary> 66 [Bindable(true), Description("获取或者设置是否自定义每一个时间轴点的外观。当属性值为True时,FirstSlotTemplate、MiddleSlotTemplate、LastSlotTemplate属性都将失效,只能设置SlotTemplate来定义每一个时间轴点的样式")] 67 public bool IsCustomEverySlot 68 { 69 get { return (bool)GetValue(IsCustomEverySlotProperty); } 70 set { SetValue(IsCustomEverySlotProperty, value); } 71 } 72 73 public static readonly DependencyProperty IsCustomEverySlotProperty = 74 DependencyProperty.Register("IsCustomEverySlot", typeof(bool), typeof(Timeline), new PropertyMetadata(false)); 75 #endregion 76 #region SlotTemplate 77 /// <summary> 78 /// 获取或者设置每个时间轴点的外观 79 /// </summary> 80 [Bindable(true), Description("获取或者设置每个时间轴点的外观。只有当IsCustomEverySlot属性为True时,该属性才生效")] 81 public DataTemplate SlotTemplate 82 { 83 get { return (DataTemplate)GetValue(SlotTemplateProperty); } 84 set { SetValue(SlotTemplateProperty, value); } 85 } 86 87 public static readonly DependencyProperty SlotTemplateProperty = 88 DependencyProperty.Register("SlotTemplate", typeof(DataTemplate), typeof(Timeline)); 89 #endregion 90 #endregion 91 #region Constructors 92 static Timeline() 93 { 94 DefaultStyleKeyProperty.OverrideMetadata(typeof(Timeline), new FrameworkPropertyMetadata(typeof(Timeline))); 95 } 96 #endregion 97 #region Override 98 protected override void PrepareContainerForItemOverride(DependencyObject element, object item) 99 { 100 int index = this.ItemContainerGenerator.IndexFromContainer(element); 101 TimelineItem timelineItem = element as TimelineItem; 102 if(timelineItem == null) 103 { 104 return; 105 } 106 if(index == 0) 107 { 108 timelineItem.IsFirstItem = true; 109 } 110 if(index == this.Items.Count - 1) 111 { 112 timelineItem.IsLastItem = true; 113 } 114 base.PrepareContainerForItemOverride(timelineItem, item); 115 } 116 protected override DependencyObject GetContainerForItemOverride() 117 { 118 return new TimelineItem(); 119 } 120 public override void OnApplyTemplate() 121 { 122 base.OnApplyTemplate(); 123 } 124 protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) 125 { 126 base.OnItemsChanged(e); 127 //以下代码是为了新增项或者移除项时,正确设置每个Item的外观 128 switch (e.Action) 129 { 130 case NotifyCollectionChangedAction.Add: 131 if (e.NewStartingIndex == 0) //如果新添加项是放在第一位,则更改原来的第一位的属性值 132 { 133 this.SetTimelineItem(e.NewStartingIndex + e.NewItems.Count); 134 } 135 //如果新添加项是放在最后一位,则更改原来的最后一位的属性值 136 if (e.NewStartingIndex == this.Items.Count - e.NewItems.Count) 137 { 138 this.SetTimelineItem(e.NewStartingIndex - 1); 139 } 140 break; 141 case NotifyCollectionChangedAction.Remove: 142 if(e.OldStartingIndex == 0) //如果移除的是第一个,则更改更新后的第一项的属性值 143 { 144 this.SetTimelineItem(0); 145 } 146 else 147 { 148 this.SetTimelineItem(e.OldStartingIndex - 1); 149 } 150 break; 151 } 152 } 153 #endregion 154 #region private function 155 /// <summary> 156 /// 设置TimelineItem的位置属性 157 /// </summary> 158 /// <param name="index"></param> 159 private void SetTimelineItem(int index) 160 { 161 if(index > this.Items.Count || index < 0) 162 { 163 return; 164 } 165 TimelineItem timelineItem = this.ItemContainerGenerator.ContainerFromIndex(index) as TimelineItem; 166 if(timelineItem == null) 167 { 168 return; 169 } 170 timelineItem.IsFirstItem = index == 0; 171 timelineItem.IsLastItem = index == this.Items.Count - 1; 172 timelineItem.IsMiddleItem = index > 0 && index < this.Items.Count - 1; 173 } 174 #endregion 175 } 176 }
样式代码:
1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 2 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ZUI="clr-namespace:ZdfFlatUI"> 3 <PathGeometry x:Key="Icon_Gou" Figures="M378.410667 850.450963C364.491852 850.450963 350.610963 845.293037 340.02963 834.939259L20.920889 523.529481C-0.279704 502.821926-0.279704 469.295407 20.920889 448.587852 42.121481 427.880296 76.48237 427.880296 97.682963 448.587852L378.410667 722.526815 925.75763 188.491852C946.958222 167.784296 981.319111 167.784296 1002.519704 188.491852 1023.720296 209.161481 1023.720296 242.688 1002.519704 263.395556L416.791704 834.939259C406.172444 845.293037 392.291556 850.450963 378.410667 850.450963L378.410667 850.450963Z" /> 4 <DataTemplate x:Key="FirstSlotTemplate"> 5 <Grid> 6 <Ellipse x:Name="Slot1" Width="15" Height="15" Fill="#30AAADAF" /> 7 <Ellipse x:Name="Slot2" Width="7" Height="7" Fill="#FF6501" /> 8 </Grid> 9 </DataTemplate> 10 <DataTemplate x:Key="LastSlotTemplate"> 11 <Grid> 12 <Ellipse x:Name="Slot1" Width="15" Height="15" Fill="#AAADAF" /> 13 <Path x:Name="path" Width="9" 14 Data="{StaticResource Icon_Gou}" 15 Fill="#FFFFFF" Stretch="Uniform" /> 16 </Grid> 17 </DataTemplate> 18 <Style TargetType="{x:Type ZUI:TimelineItem}"> 19 <Setter Property="Background" Value="Transparent" /> 20 <Setter Property="BorderBrush" Value="{Binding BorderBrush, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 21 <Setter Property="BorderThickness" Value="0" /> 22 <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 23 <Setter Property="Padding" Value="15,0,15,0" /> 24 <Setter Property="MinHeight" Value="50" /> 25 <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 26 <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 27 <Setter Property="SnapsToDevicePixels" Value="True" /> 28 <Setter Property="UseLayoutRounding" Value="True" /> 29 <Setter Property="Template"> 30 <Setter.Value> 31 <ControlTemplate TargetType="{x:Type ZUI:TimelineItem}"> 32 <Grid> 33 <Grid.RowDefinitions> 34 <RowDefinition Height="auto" /> 35 <RowDefinition Height="*" /> 36 </Grid.RowDefinitions> 37 <Grid.ColumnDefinitions> 38 <ColumnDefinition Width="auto" /> 39 <ColumnDefinition Width="*" /> 40 </Grid.ColumnDefinitions> 41 <ContentPresenter x:Name="Slot" ContentTemplate="{Binding MiddleSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 42 <Rectangle x:Name="Line" Grid.Row="1" Width="1" 43 Fill="{TemplateBinding BorderBrush}" /> 44 <ContentPresenter Grid.RowSpan="2" Grid.Column="1" 45 Margin="{TemplateBinding Padding}" 46 HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 47 VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> 48 </Grid> 49 <ControlTemplate.Triggers> 50 <!-- 51 当IsCustomEverySlot为True时,FirstSlotTemplate、MiddleSlotTemplate、LastSlotTemplate都将失效, 52 只能设置SlotTemplate来定义每一个时间轴点的样式 53 --> 54 <MultiDataTrigger> 55 <MultiDataTrigger.Conditions> 56 <Condition Binding="{Binding IsFirstItem, RelativeSource={RelativeSource Self}}" Value="True" /> 57 <Condition Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="False" /> 58 </MultiDataTrigger.Conditions> 59 <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding FirstSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 60 </MultiDataTrigger> 61 <MultiDataTrigger> 62 <MultiDataTrigger.Conditions> 63 <Condition Binding="{Binding IsLastItem, RelativeSource={RelativeSource Self}}" Value="True" /> 64 <Condition Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="False" /> 65 </MultiDataTrigger.Conditions> 66 <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding LastSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 67 </MultiDataTrigger> 68 <MultiDataTrigger> 69 <MultiDataTrigger.Conditions> 70 <Condition Binding="{Binding IsMiddleItem, RelativeSource={RelativeSource Self}}" Value="True" /> 71 <Condition Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="False" /> 72 </MultiDataTrigger.Conditions> 73 <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding MiddleSlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 74 </MultiDataTrigger> 75 <DataTrigger Binding="{Binding IsCustomEverySlot, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" Value="True"> 76 <Setter TargetName="Slot" Property="ContentTemplate" Value="{Binding SlotTemplate, RelativeSource={RelativeSource AncestorType={x:Type ZUI:Timeline}}}" /> 77 </DataTrigger> 78 <Trigger Property="IsLastItem" Value="True"> 79 <Setter TargetName="Line" Property="Visibility" Value="Collapsed" /> 80 </Trigger> 81 <Trigger Property="IsMiddleItem" Value="True"> 82 <Setter TargetName="Line" Property="Visibility" Value="Visible" /> 83 </Trigger> 84 </ControlTemplate.Triggers> 85 </ControlTemplate> 86 </Setter.Value> 87 </Setter> 88 </Style> 89 <Style TargetType="{x:Type ZUI:Timeline}"> 90 <Setter Property="Background" Value="Transparent" /> 91 <Setter Property="BorderBrush" Value="#F0F0F0" /> 92 <Setter Property="BorderThickness" Value="0" /> 93 <Setter Property="Foreground" Value="Black" /> 94 <Setter Property="HorizontalContentAlignment" Value="Left" /> 95 <Setter Property="VerticalContentAlignment" Value="Top" /> 96 <Setter Property="SnapsToDevicePixels" Value="True" /> 97 <Setter Property="UseLayoutRounding" Value="True" /> 98 <Setter Property="FirstSlotTemplate" Value="{StaticResource FirstSlotTemplate}" /> 99 <Setter Property="MiddleSlotTemplate" Value="{StaticResource LastSlotTemplate}" /> 100 <Setter Property="LastSlotTemplate" Value="{StaticResource LastSlotTemplate}" /> 101 <Setter Property="Template"> 102 <Setter.Value> 103 <ControlTemplate TargetType="{x:Type ZUI:Timeline}"> 104 <Border Background="{TemplateBinding Background}" 105 BorderBrush="{TemplateBinding BorderBrush}" 106 BorderThickness="{TemplateBinding BorderThickness}" 107 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 108 UseLayoutRounding="{TemplateBinding UseLayoutRounding}"> 109 <ZUI:ZScrollViewer> 110 <ItemsPresenter /> 111 </ZUI:ZScrollViewer> 112 </Border> 113 </ControlTemplate> 114 </Setter.Value> 115 </Setter> 116 </Style> 117 </ResourceDictionary>
在Timeline类中,有几处关键代码
protected override DependencyObject GetContainerForItemOverride() { return new TimelineItem(); }
②、在控件第一次初始化以及在后来的新增时,需要设置TimelineItem的几个依赖属性值,即设置Item具体是第一个、中间项还是最后一项,因此需要重写【PrepareContainerForItemOverride】
protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { int index = this.ItemContainerGenerator.IndexFromContainer(element); TimelineItem timelineItem = element as TimelineItem; if(timelineItem == null) { return; } if(index == 0) { timelineItem.IsFirstItem = true; } if(index == this.Items.Count - 1) { timelineItem.IsLastItem = true; } base.PrepareContainerForItemOverride(timelineItem, item); }
③、Timeline控件在运行过程中,可能会涉及到新增或者删除节点,这时同样需要实时的设置每个TimelineItem的IsFirstItem、IsMiddleItem、IsLastItem,这样呈现正确的外观
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) { base.OnItemsChanged(e); //以下代码是为了新增项或者移除项时,正确设置每个Item的外观 switch (e.Action) { case NotifyCollectionChangedAction.Add: if (e.NewStartingIndex == 0) //如果新添加项是放在第一位,则更改原来的第一位的属性值 { this.SetTimelineItem(e.NewStartingIndex + e.NewItems.Count); } //如果新添加项是放在最后一位,则更改原来的最后一位的属性值 if (e.NewStartingIndex == this.Items.Count - e.NewItems.Count) { this.SetTimelineItem(e.NewStartingIndex - 1); } break; case NotifyCollectionChangedAction.Remove: if(e.OldStartingIndex == 0) //如果移除的是第一个,则更改更新后的第一项的属性值 { this.SetTimelineItem(0); } else { this.SetTimelineItem(e.OldStartingIndex - 1); } break; } }
最终效果图:
标签:default tor 定义 metadata div out 移除 sys 中间
原文地址:http://www.cnblogs.com/zhidanfeng/p/6920719.html