先來張效果圖,
然後繼續貼
軸控件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
}
}