wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part2
来源:互联网 发布:金幻灯饰怎么样 知乎 编辑:程序博客网 时间:2024/05/17 08:12
先来张效果图,
然后继续贴
轴控件xaml :
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="http://schemas.microsoft.com/surface/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:tranvalue="clr-namespace:Transvalue.Timeline" x:Class="Transvalue.Timeline.TimelineControl" mc:Ignorable="d" Loaded="TimelineControl_Loaded" Height="540" Width="3500" > <s:SurfaceScrollViewer Name="touchPad" CanContentScroll="True" VerticalScrollBarVisibility="Disabled"PanningMode="HorizontalOnly" Width="Auto" Height="Auto" ScrollChanged="SurfaceScrollViewer_ScrollChanged" Elasticity="0.4,0.4" Grid.IsSharedSizeScope="True" HorizontalScrollBarVisibility="Hidden" > <Grid Height="Auto" x:Name="gridTimeline" Width="Auto" IsManipulationEnabled="True" TouchDown="gridTimeline_TouchDown" TouchLeave="gridTimeline_TouchLeave" Background="Black" RenderTransformOrigin="0.5,0.5"> <Grid.RowDefinitions> <RowDefinition Height="0.3*" /> <RowDefinition Height="0.7*" /> </Grid.RowDefinitions> <tranvalue:TimelineBandControl Grid.Row="1" HorizontalAlignment="Left" Height="Auto" Width="Auto"x:Name="timelineBandControl" VerticalAlignment="Top" PageSize="40"/> </Grid> </s:SurfaceScrollViewer></UserControl>
轴控件代码:
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.Navigation;using System.Windows.Shapes;using Microsoft.Surface;using Microsoft.Surface.Presentation;using Microsoft.Surface.Presentation.Controls;using Microsoft.Surface.Presentation.Input;using System.Threading.Tasks;using System.Threading;using System.Collections.ObjectModel;using System.ComponentModel;using System.Windows.Media.Animation;namespace Transvalue.Timeline{ /// <summary> /// Interaction logic for SurfaceWindow1.xaml /// </summary> public partial class TimelineControl : UserControl, INotifyPropertyChanged { /// <summary> /// 点的位置 /// </summary> private static List<TouchPoint> position = new List<TouchPoint>(); /// <summary> /// 点移动距离 /// </summary> private static List<TouchPoint> leavePosition = new List<TouchPoint>(); /// <summary> /// 更换时间轴方法(从小到大)字典 /// </summary> private static Dictionary<Predicate<TimeLineEnum.TimeLineBandType>, Func<DateTime, DateTime, ObservableCollection<TimelineLabelItem>, bool, Task<ObservableCollection<TimelineLabelItem>>>> ChangeTimeLineBandBigFuncDict = new Dictionary<Predicate<TimeLineEnum.TimeLineBandType>, Func<DateTime, DateTime, ObservableCollection<TimelineLabelItem>, bool, Task<ObservableCollection<TimelineLabelItem>>>>(); /// <summary> /// 时间轴对应文字字典 /// </summary> private static Dictionary<TimeLineEnum.TimeLineBandType, string> timelineBandDict = new Dictionary<TimeLineEnum.TimeLineBandType, string>(); /// <summary> /// 获取该年一共有多少天 /// </summary> private static Func<int, int> GetDaysByYearFunc; private static Func<TimeLineEnum.TimeLineBandType, ObservableCollection<TimelineLabelItem>, int> GetTimelineLabelItems; /// <summary> /// 获取该月一共有多少天 /// </summary> private static Func<int, int, int> GetDaysOfMonthFunc; /// <summary> /// 根据点移动位置以及数量来判断放大或缩小 /// </summary> private static Func<List<TouchPoint>, List<TouchPoint>, int> TransScatterFunc; /// <summary> /// 根据标签类型来删除 /// </summary> private static Func<TimeLineEnum.TimeLineBandType, ObservableCollection<TimelineLabelItem>, ObservableCollection<TimelineLabelItem>, ObservableCollection<TimelineLabelItem>> DelLabelItemsByType; /// <summary> /// 根据父坐标生成子坐标 /// <para>int 最大生成子项数</para> /// <para>TimelineType 需要生成的子相熟类型</para> /// <para>TimelineLabelItem 需要扩展的父坐标</para> /// <para>ObservableCollection 返回值</para> /// </summary> private static Func<DateTime, DateTime, int, TimeLineEnum.TimeLineBandType, TimeLineEnum.TimelineLabelItemState, ObservableCollection<TimelineLabelItem>, Task<ObservableCollection<TimelineLabelItem>>> ExtendsTimeline; /// <summary> /// 生成根坐标 /// </summary> private static Func<DateTime, TimeLineEnum.TimeLineBandType, ObservableCollection<TimelineLabelItem>, TimeLineEnum.TimelineLabelItemState, DateTime, Task<ObservableCollection<TimelineLabelItem>>> GenericRootLabelItems; /// <summary> /// 临时坐标 /// </summary> private static int index = 0; private static bool isFirst = true; #region 开始时间 public static DependencyProperty startDate = DependencyProperty.Register("StartDate", typeof(DateTime), typeof(TimelineControl) , new PropertyMetadata(new PropertyChangedCallback(StartDateCallBack))); public DateTime StartDate { get { return (DateTime)GetValue(startDate); } set { SetValue(startDate, value); } } private static void StartDateCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e) { TimelineControl timelineControl = sender as TimelineControl; if (e.Property == startDate) { timelineControl.StartDate = (DateTime)e.NewValue; } } #endregion #region 结束时间 public static DependencyProperty endDate = DependencyProperty.Register("EndDate", typeof(DateTime), typeof(TimelineControl) , new PropertyMetadata(new PropertyChangedCallback(EndDateCallBack))); public DateTime EndDate { get { return (DateTime)GetValue(endDate); } set { SetValue(endDate, value); } } private static void EndDateCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e) { TimelineControl timelineControl = sender as TimelineControl; if (e.Property == startDate) { timelineControl.EndDate = (DateTime)e.NewValue; } } #endregion #region 时间轴类型 private static TimeLineEnum.TimeLineBandType currentMode; public static DependencyProperty defaultTimelineMode = DependencyProperty.Register("DefaultTimelineMode", typeof(int), typeof(TimelineControl), new PropertyMetadata(new PropertyChangedCallback(CurrentTimelineModeCallBack))); public int DefaultTimelineMode { get { return (int)GetValue(defaultTimelineMode); } set { SetValue(defaultTimelineMode, value); } } private static void CurrentTimelineModeCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var timelineBand = sender as TimelineControl; if (e.Property == defaultTimelineMode) { timelineBand.DefaultTimelineMode = (int)e.NewValue; currentMode = (TimeLineEnum.TimeLineBandType)timelineBand.DefaultTimelineMode; } } #endregion #region 时间轴事件数据源 public static DependencyProperty timelineEventSource = DependencyProperty.Register("TimelineEventSource", typeof(ObservableCollection<TimelineEventItem>), typeof(TimelineControl) , new PropertyMetadata(new PropertyChangedCallback(timelineEventSourceCallBack))); public ObservableCollection<TimelineEventItem> TimelineEventSource { get { return (ObservableCollection<TimelineEventItem>)GetValue(timelineEventSource); } set { SetValue(timelineEventSource, value); } } private static void timelineEventSourceCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e) { TimelineControl o = sender as TimelineControl; if (e.Property == timelineEventSource) o.TimelineEventSource = (ObservableCollection<TimelineEventItem>)e.NewValue; } #endregion #region 默认轴之间的宽度 public static DependencyProperty defaultItemWidth = DependencyProperty.Register("DefaultItemWidth", typeof(double), typeof(TimelineControl), new PropertyMetadata(new PropertyChangedCallback(DefaultItemWidthCallBack))); public double DefaultItemWidth { get { return (double)GetValue(defaultItemWidth); } set { SetValue(defaultItemWidth, value); } } private static void DefaultItemWidthCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e) { var timelineBand = sender as TimelineControl; if (e.Property == defaultItemWidth) { timelineBand.DefaultItemWidth = (double)e.NewValue; TimelineBandControl.defaultItemWidth = timelineBand.DefaultItemWidth; } } #endregion #region 注册自定义事件和参数 #region 加载完毕 public static readonly RoutedEvent LoadComplatedEvent; public class LoadComplatedEventArgs : RoutedEventArgs { public bool ok { get; set; } } public delegate void LoadComplatedEventHandler(object sender, LoadComplatedEventArgs e); public event LoadComplatedEventHandler LoadComplatedEH { add { AddHandler(TimelineControl.LoadComplatedEvent, value); } remove { RemoveHandler(TimelineControl.LoadComplatedEvent, value); } } #endregion #region 加载中 public static readonly RoutedEvent LoadingEvent; public class LoadingEventArgs : RoutedEventArgs { public bool ok { get; set; } } public delegate void LoadingEventHandler(object sender, LoadingEventArgs e); public event LoadingEventHandler LoadingEH { add { AddHandler(TimelineControl.LoadingEvent, value); } remove { RemoveHandler(TimelineControl.LoadingEvent, value); } } #endregion #region 加载SVI事件 public static readonly RoutedEvent ShowScatterEvent; public class ShowScatterEventArgs : RoutedEventArgs { public UIElement svi { get; set; } } public delegate void ShowScatterEventHandler(object sender, ShowScatterEventArgs e); public event ShowScatterEventHandler ShowScatterEH { add { AddHandler(TimelineControl.ShowScatterEvent, value); } remove { RemoveHandler(TimelineControl.ShowScatterEvent, value); } } #endregion #endregion #region 初始化 public TimelineControl() { InitializeComponent(); if (isFirst) { isFirst = false; InitializeControlData(); InitializeControlFunction(); } timelineBandControl.LoadComplatedEH += ((sender, e) => { LoadComplatedEventArgs args = new LoadComplatedEventArgs(); args.RoutedEvent = LoadComplatedEvent; args.ok = true; RaiseEvent(args); }); timelineBandControl.ShowScatterEH += ((sender, eventArgs) => { ShowScatterEventArgs args = new ShowScatterEventArgs(); args.svi = eventArgs.svi; args.RoutedEvent = ShowScatterEvent; RaiseEvent(args); }); timelineBandControl.ShowDetailEH += (async (sender, eventArgs) => { var start = eventArgs.startDate; var mode = eventArgs.showMode; var end = eventArgs.endDate; clearCache(); currentMode--; if (await timelineBandControl.doAnimation(true)) await loadTimeline(start, end, mode, true); }); } static TimelineControl() { LoadComplatedEvent = EventManager.RegisterRoutedEvent( "LoadComplatedEvent", RoutingStrategy.Bubble, typeof(LoadComplatedEventHandler), typeof(TimelineControl)); LoadingEvent = EventManager.RegisterRoutedEvent( "LoadingEvent", RoutingStrategy.Bubble, typeof(LoadingEventHandler), typeof(TimelineControl)); ShowScatterEvent = EventManager.RegisterRoutedEvent( "ShowScatterEvent", RoutingStrategy.Bubble, typeof(ShowScatterEventHandler), typeof(TimelineControl)); } /// <summary> /// 初始化控件数据 /// </summary> /// <returns></returns> private async void InitializeControlData() { await Task.Factory.StartNew(() => { timelineBandDict.Add(TimeLineEnum.TimeLineBandType.Days, "日"); timelineBandDict.Add(TimeLineEnum.TimeLineBandType.Months, "月"); timelineBandDict.Add(TimeLineEnum.TimeLineBandType.Years, "年"); timelineBandDict.Add(TimeLineEnum.TimeLineBandType.Decades, "年"); }); } /// <summary> /// 初始化控件方法 /// </summary> /// <returns></returns> private async void InitializeControlFunction() { #region 初始化方法 GetDaysByYearFunc = (year => { var dt = new DateTime(year, 12, 31); int days = dt.DayOfYear; return 0; }); GetTimelineLabelItems = ((type, controlItems) => { return (from item in controlItems where item.TimelineType.Equals(type) select item).Count(); }); GetDaysOfMonthFunc = ((year, month) => { int nextMonth = new DateTime(year, month, 1).AddMonths(1).DayOfYear; int currentMonth = new DateTime(year, month, 1).DayOfYear; if (month == 12) return 31; else return nextMonth - currentMonth; }); //反回0放大 1缩小 TransScatterFunc = ((position, leavePosition) => { var point = new List<double>(); position.ForEach(p => { leavePosition.ForEach(l => { if (p.Id == l.Id) { point.Add(p.Position); point.Add(l.Position); } }); }); if (point.Count > 3) { var tPointA = point[0]; //按下去的点A var lPointA = point[1]; //松开的点A var tPointB = point[2]; //按下去的点B var lPointB = point[3]; //松开的点B if ((tPointA < lPointA && lPointA - tPointA > 10) && (tPointB > lPointB && tPointB - lPointB > 10)) return 1; //缩小操作 if ((tPointA > lPointA && tPointA - lPointA > 10) && (tPointB < lPointB && lPointB - tPointB > 10)) return 0; //放大操作 } return -1; }); DelLabelItemsByType = ((delType, items, controlItems) => { var delItems = new ObservableCollection<TimelineLabelItem>(controlItems. Where(item => item.TimelineType.Equals(delType))); delItems.ForEach(delItem => { items.Remove(delItem); delItem.TimelineState = TimeLineEnum.TimelineLabelItemState.Del; items.Add(delItem); }); return items; }); ExtendsTimeline = (async (start, end, max, type, state, items) => { return await Task.Run(() => { var resultItems = new ObservableCollection<TimelineLabelItem>(); if (type != TimeLineEnum.TimeLineBandType.Days) for (DateTime i = start; i <= end; i = i.AddMonths(1)) { var sonItem = new TimelineLabelItem(); var content = i.Year + timelineBandDict[type + 1] + i.Month + timelineBandDict[type]; sonItem.TimelineType = type; sonItem.TimelineLabelContent = content; sonItem.TimelineState = state; sonItem.TimelineDate = i; resultItems.Add(sonItem); } else { for (DateTime i = start; i < end; i = i.AddDays(1)) { var item = new TimelineLabelItem(); item.TimelineIndex = index++; item.TimelineState = TimeLineEnum.TimelineLabelItemState.New; item.TimelineDate = i; item.TimelineLabelContent = i.Year + timelineBandDict[type + 2] + i.Month + timelineBandDict[type + 1] + i.Day + timelineBandDict[type]; item.TimelineType = TimeLineEnum.TimeLineBandType.Days; resultItems.Add(item); } } resultItems.Distinct(new TimelineLabelItemComparer()); return resultItems; }); }); GenericRootLabelItems = (async (start, currentType, items, newState, end) => { return await Task.Run(() => { for (DateTime i = start; i < end; i = i.AddYears(1)) { var item = new TimelineLabelItem(); item.TimelineIndex = i.Year - start.Year; var content = i.Year + timelineBandDict[currentType]; item.TimelineLabelContent = content; item.TimelineState = newState; item.TimelineType = currentType; item.TimelineDate = i; items.Add(item); } return items; }); }); #endregion #region 初始化字典方法 await Task.Factory.StartNew(() => { #region 十年坐标 ChangeTimeLineBandBigFuncDict.Add(type => type.Equals(TimeLineEnum.TimeLineBandType.Decades), async (start, end, controlItems, detail) => { var currentType = TimeLineEnum.TimeLineBandType.Decades; var items = new ObservableCollection<TimelineLabelItem>(); var newState = TimeLineEnum.TimelineLabelItemState.New; var maxYear = end.Year - start.Year; Thread.Sleep(500); if ((null == decadesCache || decadesCache.Count == 0)) { items = await Task.Run<ObservableCollection<TimelineLabelItem>>(() => { for (DateTime i = start; i < end; i = i.AddYears(10)) { var item = new TimelineLabelItem(); item.TimelineIndex = (i.Year - start.Year) / 10; var content = i.Year + timelineBandDict[currentType] + " 至 " + i.AddYears(9).Year + timelineBandDict[currentType]; item.TimelineLabelContent = content; item.TimelineState = newState; item.TimelineType = currentType; item.TimelineDate = i.AddYears(9); items.Add(item); } return items; }); Pollute.log("完毕:" + items.Count); if (!detail) saveCache(currentMode, new ObservableCollection<TimelineLabelItem>(items.OrderBy(item => item.TimelineIndex))); else return items; } return decadesCache; }); #endregion #region 年坐标 ChangeTimeLineBandBigFuncDict.Add(type => type.Equals(TimeLineEnum.TimeLineBandType.Years), async (start, end, controlItems, detail) => { var sonItems = new ObservableCollection<TimelineLabelItem>(); var currentType = TimeLineEnum.TimeLineBandType.Years; var items = new ObservableCollection<TimelineLabelItem>(); var newState = TimeLineEnum.TimelineLabelItemState.New; var maxYear = end.Year - start.Year; Thread.Sleep(500); if ((null == yearCache || yearCache.Count == 0)) { Pollute.log("开始生成 type:" + currentType); items = await GenericRootLabelItems(start, currentType, items, newState, end); Pollute.log("完毕:" + items.Count); if (!detail) saveCache(currentMode, new ObservableCollection<TimelineLabelItem>(items.OrderBy(item => item.TimelineIndex))); else return items; } return yearCache; }); #endregion #region 月坐标 ChangeTimeLineBandBigFuncDict.Add(type => type.Equals(TimeLineEnum.TimeLineBandType.Months), async (start, end, controlItems, detail) => { var currentType = TimeLineEnum.TimeLineBandType.Months; var newState = TimeLineEnum.TimelineLabelItemState.New; var items = controlItems; var maxYear = end.Year - start.Year; var max = 12; //12代表12个月 Thread.Sleep(500); if ((null == monthCache || monthCache.Count == 0)) { Pollute.log("开始生成 type:" + currentType); items = new ObservableCollection<TimelineLabelItem>(); items = await ExtendsTimeline(start, end, max, currentType, newState, items); Pollute.log("完毕:" + items.Count); if (!detail) saveCache(currentMode, new ObservableCollection<TimelineLabelItem>(items.OrderBy(item => item.TimelineIndex))); else return items; } return monthCache; }); #endregion #region 日坐标 ChangeTimeLineBandBigFuncDict.Add(type => type.Equals(TimeLineEnum.TimeLineBandType.Days), async (start, end, controlItems, detail) => //只负责生成日 { var currentType = TimeLineEnum.TimeLineBandType.Days; var newState = TimeLineEnum.TimelineLabelItemState.New; var items = controlItems; var maxYear = end.Year - start.Year; var max = 12; //12代表12个月 Thread.Sleep(500); if ((null == dayCache || dayCache.Count == 0)) { Pollute.log("开始生成 type:" + currentType); items = new ObservableCollection<TimelineLabelItem>(); items = await ExtendsTimeline(start, end, max, currentType, newState, items); if (!detail) saveCache(currentMode, new ObservableCollection<TimelineLabelItem>(items.OrderBy(item => item.TimelineDate))); else return items; } return dayCache; }); #endregion }); #endregion } private async void TimelineControl_Loaded(object sender, RoutedEventArgs e) { await loadTimeline(StartDate, EndDate, (TimeLineEnum.TimeLineBandType)DefaultTimelineMode, false); } #endregion #region 加载时间轴 static bool isBusyLoading = false; public async Task loadTimeline(DateTime start, DateTime end, TimeLineEnum.TimeLineBandType type, bool detail) { if (!isBusyLoading) { isBusyLoading = true; Console.WriteLine("开始加载"); LoadingEventArgs args = new LoadingEventArgs(); args.RoutedEvent = LoadingEvent; args.ok = true; RaiseEvent(args); var controlItems = timelineBandControl.TimelineLabels; var resultItems = await Task.Run<ObservableCollection<TimelineLabelItem>>(GetItemsAsync(start, end, type, controlItems, detail)); timelineBandControl.CurrentTimelineMode = (int)type; timelineBandControl.TimelineLabels = resultItems; timelineBandControl.TimelineEventSource = TimelineEventSource; isBusyLoading = false; Console.WriteLine("加载完毕"); } } private static Func<Task<ObservableCollection<TimelineLabelItem>>> GetItemsAsync(DateTime start, DateTime end, TimeLineEnum.TimeLineBandType type, ObservableCollection<TimelineLabelItem> controlItems, bool detail) { return async () => { //根据设定类型加载时间轴 return await ChangeTimeLineBandBigFuncDict.Where(item => item.Key(type)).ForEach(async item => { Pollute.log("key:" + type + " 开始等待"); return await item.Value(start, end, controlItems, detail); })[0]; }; } #endregion #region 多点事件捕捉 private async void gridTimeline_TouchDown(object sender, TouchEventArgs e) { await Task.Factory.StartNew(() => { Console.WriteLine("ID:" + e.TouchDevice.Id + "位置:" + e.TouchDevice.GetTouchPoint(this).Position.X); e.TouchDevice.Synchronize(); SavePosition(e, position); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); } /// <summary> /// 触摸移开的时候记录事件 /// </summary> /// <param na me="sender"></param> /// <param name="e"></param> private async void gridTimeline_TouchLeave(object sender, TouchEventArgs e) { Pollute.log(e.TouchDevice.Id + ":开始等待放大缩小结果"); var result = await Task.Factory.StartNew(() => { SavePosition(e, leavePosition); if (leavePosition.Count < 2) return -1; return TransScatterFunc(position, leavePosition); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); try { if (result == 0 && currentMode < TimeLineEnum.TimeLineBandType.Decades) { position.Clear(); leavePosition.Clear(); if (await timelineBandControl.doAnimation(false)) await changeTimelineType(++currentMode); } else if (result == 1 && currentMode > TimeLineEnum.TimeLineBandType.Days) { position.Clear(); leavePosition.Clear(); if (await timelineBandControl.doAnimation(true)) await changeTimelineType(--currentMode); } else return; } catch (Exception ex) { MessageBox.Show("放大缩小报错:" + ex.ToString()); } } #region 保存点 private void SavePosition(TouchEventArgs e, List<TouchPoint> position) { if (position.Where(s => s.Id.Equals(e.TouchDevice.Id)).Count<TouchPoint>().Equals(0)) { var point = new TouchPoint(); point.Id = e.TouchDevice.Id; point.Position = e.TouchDevice.GetPosition(this).X; position.Add(point); } else { TouchPoint point = position.Where<TouchPoint>(s => s.Id.Equals(e.TouchDevice.Id)).First(); point.Position = e.TouchDevice.GetPosition(this).X; } if (position.Count > 2) { try { Console.WriteLine("超过3个点了"); position.RemoveAt(0); } catch (Exception ex) { MessageBox.Show("超过3个点了:" + ex.ToString()); } } } #endregion #endregion #region 放大或缩小时间轴 private async Task changeTimelineType(TimeLineEnum.TimeLineBandType type) { await loadTimeline(StartDate, EndDate, type, false); leavePosition.Clear(); } #endregion #region 滚动翻页 private async void SurfaceScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { var ssv = sender as SurfaceScrollViewer; if ((e.HorizontalOffset > ssv.ScrollableWidth - 30) && ssv.ScrollableWidth != 0) { Pollute.log("翻下一页"); await timelineBandControl.ChangeBand(true); } } #endregion #region 时间轴数据缓存 private static ObservableCollection<TimelineLabelItem> monthCache; private static ObservableCollection<TimelineLabelItem> dayCache; private static ObservableCollection<TimelineLabelItem> yearCache; private static ObservableCollection<TimelineLabelItem> decadesCache; private void saveCache(TimeLineEnum.TimeLineBandType type, ObservableCollection<TimelineLabelItem> data) { switch (type) { case TimeLineEnum.TimeLineBandType.Days: dayCache = data; break; case TimeLineEnum.TimeLineBandType.Months: monthCache = data; break; case TimeLineEnum.TimeLineBandType.Years: yearCache = data; break; case TimeLineEnum.TimeLineBandType.Decades: decadesCache = data; break; default: break; } } private void clearCache() { dayCache = null; monthCache = null; yearCache = null; decadesCache = null; } #endregion #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } #endregion }}
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part2
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part1
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part3
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part4
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part5
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part6
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part7
- 基于 wpf .net Framework 4.5 multitouch 制作 多点触控 office 浏览器。支持 excel ppt word浏览 beta版
- WPF 多点触控开发资料整理
- wpf inkcanvas 多点绘画
- 多点触控
- android多点触控
- Android多点触控
- 多点触控
- 触摸屏多点触控
- android 多点触控
- android 多点触控
- 多点触控参数
- linux X Window System(私房菜)
- 终止处理程序
- stringbuffer 和 string
- 建造者模式c++实现
- proxool连接池的配置【结合spring和hibernate】
- wpf+.net 4.5 surface2.0 = 异步多点触控 时间轴 part2
- DAPM之一:概述
- Windows Phone开发如何保存铃声?
- 解决办法:warning: Clock skew detected. Your build may be incomplete.
- 鸡尾酒排序的PHP实现 Cocktail Sort
- mySql 连接问题
- nor flash和nand flash的区别
- Android建立dialog
- ADF Blog 列表