wpf+.net 4.5 surface2.0 = 異步多點觸控 時間軸 part3

座標軸xaml:

<UserControl
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Transvalue.Timeline" x:Class="Transvalue.Timeline.TimelineBandControl" 
             mc:Ignorable="d" 
    Width="Auto"
    Name="timelineBandControl"
             >
    <UserControl.Resources>
        <Style x:Key="TimelineLabel" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid>
                            <ContentPresenter HorizontalAlignment="Center" Margin="17,19,17,24" RecognizesAccessKey="True" 
							SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
							 VerticalAlignment="Center" Content="{TemplateBinding Content}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="FontFamily" Value="/Transvalue.Timeline;component/Fonts/#Segoe UI Light"/>
            <Setter Property="Width" Value="200"/>
            <Setter Property="Foreground" Value="White"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=DataContext}"
                             Value="1">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard Name="big">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Width" Duration="0:0:0.5"
                                                 To="800">
                                </DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
                <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=DataContext}"
                             Value="0">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard Name="Small">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Width" Duration="0:0:0.5"
                                                 To="200">
                                </DoubleAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </UserControl.Resources>
    <Grid Width="Auto" Height="Auto">
        <Grid.RowDefinitions>
            <RowDefinition Height="0.40*"></RowDefinition>
            <RowDefinition Height="0.10*"></RowDefinition>
            <RowDefinition Height="0.40*"></RowDefinition>
        </Grid.RowDefinitions>
        <WrapPanel Width="Auto" Height="Auto" Name="timelineEventItems"></WrapPanel>
        <WrapPanel x:Name="timelineLabelItems" Width="Auto" Height="Auto" Grid.Row="2"></WrapPanel>
        <WrapPanel x:Name="timelinePoint" Width="Auto" Height="Auto" Grid.Row="1"></WrapPanel>
    </Grid>
</UserControl>


 

座標軸 代碼:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Surface.Presentation.Controls;

namespace Transvalue.Timeline
{
    /// <summary>
    /// TimelineBandControl.xaml 的交互邏輯
    /// </summary>
    public partial class TimelineBandControl : UserControl, INotifyPropertyChanged
    {

        private static Style timelineLabelStyle;
        private static int currentPageIndex = 0;  //初始當前頁
        private static int totalPage = 0; //最大頁數
        private static int changedBand = 0; //0不變 1變大 2縮小
        Dictionary<Predicate<string>, Action> PropertyChangedDictAction = new Dictionary<Predicate<string>, Action>();
        Dictionary<Predicate<TimeLineEnum.TimeLineBandType>, Func<TimelineLabelItem, ObservableCollection<TimelineEventItem>, TimelineEventItemControl, bool, bool>>
            TimelineEventGenericDictAction =
            new Dictionary<Predicate<TimeLineEnum.TimeLineBandType>, Func<TimelineLabelItem, ObservableCollection<TimelineEventItem>, TimelineEventItemControl, bool, bool>>();

        #region 需要顯示的數據標籤
        public static ObservableCollection<TimelineLabelItem> tempTimelineLabels;
        public static DependencyProperty timelineLabels = DependencyProperty.Register("TimelineLabelSource",
            typeof(ObservableCollection<TimelineLabelItem>), typeof(TimelineBandControl)
            , new PropertyMetadata(new PropertyChangedCallback(TimelineLabelsCallBack)));

        public ObservableCollection<TimelineLabelItem> TimelineLabels
        {
            get
            {
                return (ObservableCollection<TimelineLabelItem>)GetValue(timelineLabels);
            }
            set
            {
                SetValue(timelineLabels, value);
                OnPropertyChanged("TimelineLabels");
            }
        }

        private static void TimelineLabelsCallBack(DependencyObject sender,
            DependencyPropertyChangedEventArgs e)
        {

        }
        #endregion

        #region 時間軸顯示項數量
        public static DependencyProperty pageSize = DependencyProperty.Register("PageSize",
            typeof(int), typeof(TimelineBandControl),
            new PropertyMetadata(new PropertyChangedCallback(TimelinePageSizeCallBack)));

        public int PageSize
        {
            get
            {
                return (int)GetValue(pageSize);
            }
            set
            {
                SetValue(pageSize, value);
                OnPropertyChanged("PageSize");
            }
        }

        private static void TimelinePageSizeCallBack(DependencyObject sender,
            DependencyPropertyChangedEventArgs e)
        {
            var timelineBand = sender as TimelineBandControl;
            if (e.Property == pageSize)
            {
                timelineBand.PageSize = (int)e.NewValue;
            }
        }
        #endregion

        #region 當前顯示模式
        private static int defaultTimelineMode = -1;
        public static DependencyProperty currentTimelineMode = DependencyProperty.Register("CurrentTimelineMode",
            typeof(int), typeof(TimelineBandControl),
            new PropertyMetadata(new PropertyChangedCallback(CurrentTimelineModeCallBack)));

        public int CurrentTimelineMode
        {
            get
            {
                return (int)GetValue(currentTimelineMode);
            }
            set
            {
                SetValue(currentTimelineMode, value);
                OnPropertyChanged("CurrentTimelineMode");
            }
        }

        private static void CurrentTimelineModeCallBack(DependencyObject sender,
            DependencyPropertyChangedEventArgs e)
        {
            if (-1 != defaultTimelineMode && defaultTimelineMode != (int)e.NewValue)
                changedBand = defaultTimelineMode < (int)e.NewValue ? 1 : 2;
            else
                changedBand = 0;
            defaultTimelineMode = (int)e.NewValue;
        }
        #endregion

        #region 事件數據源
        private static int currentIndexInBand = 0;
        public static DependencyProperty timelineEventSource = DependencyProperty.Register("TimelineEventSource",
            typeof(ObservableCollection<TimelineEventItem>),
            typeof(TimelineBandControl)
           , new PropertyMetadata(new PropertyChangedCallback(timelineEventSourceCallBack)));

        public ObservableCollection<TimelineEventItem> TimelineEventSource
        {
            get { return (ObservableCollection<TimelineEventItem>)GetValue(timelineEventSource); }
            set
            {
                SetValue(timelineEventSource, value);
                OnPropertyChanged("TimelineEventSource");
            }
        }

        private static void timelineEventSourceCallBack(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
        }
        #endregion

        #region 自定義事件

        #region 加載詳細座標事件
        public static readonly RoutedEvent ShowDetailEvent;

        public class ShowDetailEventArgs : RoutedEventArgs
        {
            public TimeLineEnum.TimeLineBandType showMode
            {
                get;
                set;
            }
            public DateTime startDate
            {
                get;
                set;
            }
            public DateTime endDate
            {
                get;
                set;
            }
        }
        public delegate void ShowDetailEventHandler(object sender,
             ShowDetailEventArgs e);
        public event ShowDetailEventHandler ShowDetailEH
        {
            add
            {
                AddHandler(TimelineBandControl.ShowDetailEvent,
                    value);
            }
            remove
            {
                RemoveHandler(TimelineBandControl.ShowDetailEvent,
                    value);
            }
        }
        #endregion

        #region 加載mdiWindow事件
        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(TimelineBandControl.ShowScatterEvent,
                    value);
            }
            remove
            {
                RemoveHandler(TimelineBandControl.ShowScatterEvent,
                    value);
            }
        }
        #endregion

        #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(TimelineBandControl.LoadComplatedEvent,
                    value);
            }
            remove
            {
                RemoveHandler(TimelineBandControl.LoadComplatedEvent,
                    value);
            }
        }
        #endregion

        static TimelineBandControl()
        {
            ShowScatterEvent = EventManager.RegisterRoutedEvent(
               "ShowScatterEvent",
               RoutingStrategy.Bubble,
               typeof(ShowScatterEventHandler),
               typeof(TimelineBandControl));

            LoadComplatedEvent = EventManager.RegisterRoutedEvent(
                "LoadComplatedEvent",
                RoutingStrategy.Bubble,
                typeof(LoadComplatedEventHandler),
                typeof(TimelineBandControl));

            ShowDetailEvent = EventManager.RegisterRoutedEvent(
             "ShowDetailEvent",
             RoutingStrategy.Bubble,
             typeof(ShowDetailEventHandler),
             typeof(TimelineBandControl));
        }

        #endregion

        #region 默認軸之間的寬度
        public static double defaultItemWidth;

        public double DefaultItemWidth
        {
            get
            {
                return defaultItemWidth;
            }
            set
            {
                if (defaultItemWidth != value)
                {
                    defaultItemWidth = value;
                    OnPropertyChanged("DefaultItemWidth");
                }
            }
        }
        #endregion

        public TimelineBandControl()
        {
            InitializeComponent();
            InitializeDictoinary();
            timelineLabelStyle = Resources["TimelineLabel"] as Style;
            this.PropertyChanged += ((sender, e) =>
            {
                PropertyChangedDictAction.Where(s => s.Key(e.PropertyName)).ForEach(s =>
                {
                    Console.WriteLine("進來了" + e.PropertyName);
                    s.Value();
                });
            });
        }

        private async void InitializeDictoinary()
        {
            await Task.Run(() =>
            {
                #region 屬性變更通知方法
                PropertyChangedDictAction.Add(item => item.Equals("TimelineLabels"), () =>
                {
                    if (null != TimelineLabels && TimelineLabels.Count != 0)
                    {
                        totalPage = TimelineLabels.Count / PageSize;
                        Console.WriteLine("進來字典" + totalPage);
                        Console.WriteLine("進來字典標籤數:" + TimelineLabels.Count);
                        GenericTimelineLabelByData(TimelineLabels, PageSize, currentPageIndex);
                    }
                });

                PropertyChangedDictAction.Add(item => item.Equals("PageSize"), () =>
                {
                    if (PageSize > 200)
                    {
                        Console.WriteLine("警告,分頁數組不要超過200會引起系統緩慢");
                        PageSize = 200;
                    }
                });

                PropertyChangedDictAction.Add(item => item.Equals("DefaultItemWidth"), () =>
                {

                });


                PropertyChangedDictAction.Add(item => item.Equals("TimelineEventSource"), () =>
                {

                });

                PropertyChangedDictAction.Add(item => item.Equals("CurrentTimelineMode"), () =>
                {

                });
                #endregion

                #region 生成事件字典
                TimelineEventGenericDictAction.Add(item => item == TimeLineEnum.TimeLineBandType.Days, (item, events, eventControl, getEvent) =>
                {
                    foreach (var e in events)
                    {
                        Console.WriteLine("判斷天事件時間是:" + e.Date.ToShortDateString());
                        Console.WriteLine("判斷天座標的時間是:" + item.TimelineDate.ToShortDateString());
                        if (e.Date.Day == item.TimelineDate.Day &&
                            e.Date.Year == item.TimelineDate.Year &&
                            e.Date.Month == item.TimelineDate.Month)
                        {
                            eventControl.DataContext = e;
                            timelineEventItems.Children.Add(eventControl);
                            getEvent = true;
                            break;
                        }
                        return getEvent;
                    }
                    return false;
                });
                TimelineEventGenericDictAction.Add(item => item == TimeLineEnum.TimeLineBandType.Months, (item, events, eventControl, getEvent) =>
                {
                    foreach (var e in events)
                    {
                        Console.WriteLine("判斷月事件時間是:" + e.Date.ToShortDateString());
                        Console.WriteLine("判斷月座標的時間是:" + item.TimelineDate.ToShortDateString());
                        if (e.Date.Year == item.TimelineDate.Year && e.Date.Month == item.TimelineDate.Month)
                        {
                            var o = new TimelineEventItem();
                            o.Content = "month";
                            o.Date = e.Date;
                            o.EventType = TimelineEventEnum.TimelineEventType.Detail;
                            eventControl.Name = o.Content + o.Date.Year + o.Date.Month;
                            eventControl.DataContext = o;
                            if (timelineEventItems.Children.IndexOf(eventControl) == -1)
                            {
                                timelineEventItems.Children.Add(eventControl);
                                getEvent = true;
                                break;
                            }
                        }
                        return getEvent;
                    }
                    return false;
                });
                TimelineEventGenericDictAction.Add(item => item == TimeLineEnum.TimeLineBandType.Years, (item, events, eventControl, getEvent) =>
                {
                    foreach (var e in events)
                    {
                        Console.WriteLine("判斷年事件時間是:" + e.Date.ToShortDateString());
                        Console.WriteLine("判斷年座標的時間是:" + item.TimelineDate.ToShortDateString());
                        if (e.Date.Year == item.TimelineDate.Year)
                        {
                            var o = new TimelineEventItem();
                            o.Content = "year";
                            o.Date = e.Date;
                            o.EventType = TimelineEventEnum.TimelineEventType.Detail;
                            eventControl.DataContext = o;
                            eventControl.Name = o.Content + o.Date.Year + o.Date.Month;
                            if (timelineEventItems.Children.IndexOf(eventControl) == -1)
                            {
                                timelineEventItems.Children.Add(eventControl);
                                getEvent = true;
                                break;
                            }
                        }
                        return getEvent;
                    }
                    return false;
                });
                TimelineEventGenericDictAction.Add(item => item == TimeLineEnum.TimeLineBandType.Decades,
                    (item, events, eventControl, getEvent) =>
                    {
                        foreach (var e in events)
                        {
                            Console.WriteLine("判斷十年事件時間是:" + e.Date.ToShortDateString());
                            Console.WriteLine("判斷十年座標的時間是:" + item.TimelineDate.ToShortDateString());
                            if (e.Date.Year <= item.TimelineDate.Year && e.Date.Year >= item.TimelineDate.AddYears(-9).Year)
                            {
                                var o = new TimelineEventItem();
                                o.Content = "decade";
                                o.EventType = TimelineEventEnum.TimelineEventType.Detail;
                                o.Date = e.Date;
                                eventControl.DataContext = o;
                                eventControl.Name = o.Content + o.Date.Year + o.Date.Month;
                                if (timelineEventItems.Children.IndexOf(eventControl) == -1)
                                {
                                    timelineEventItems.Children.Add(eventControl);
                                    getEvent = true;
                                    break;
                                }
                            }
                            return getEvent;
                        }
                        return false;
                    });
                #endregion
            });
        }

        public async Task ChangeBand(bool o)
        {
            await Task.Factory.StartNew(() =>
            {
                totalPage = TimelineLabels.Count / PageSize;
                if (currentPageIndex <= totalPage && o) currentPageIndex++;
                else return;
                GenericTimelineLabelByData(TimelineLabels, PageSize, currentPageIndex);
            }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
        }

        /// <summary>
        /// 分頁生成時間軸
        /// </summary>
        /// <param name="source"></param>
        /// <param name="pageSize"></param>
        /// <param name="pageIndex"></param>
        /// <returns></returns>
        private async void GenericTimelineLabelByData(ObservableCollection<TimelineLabelItem> source,
            int pageSize, int pageIndex)
        {
            var skip = pageSize * pageIndex;
            if (changedBand == 0)
            {
                //翻頁操作
                tempTimelineLabels = new ObservableCollection<TimelineLabelItem>
                    (source.Skip(skip).
                    Take(pageSize).OrderBy(item => item.TimelineIndex));
            }
            else
            {
                //換軸操作
                var takeCount = timelineLabelItems.Children.Count > PageSize ? timelineLabelItems.Children.Count : PageSize;
                tempTimelineLabels = new ObservableCollection<TimelineLabelItem>
                    (source.Take(takeCount).
                    OrderBy(item => item.TimelineDate));
                timelinePoint.Children.Clear();
                timelineLabelItems.Children.Clear();
                timelineEventItems.Children.Clear();
                currentIndexInBand = 0;
                changedBand = 0;
            }
            await BeginGeneric();
            await GenericEvent();
            LoadComplatedEventArgs args = new LoadComplatedEventArgs();
            args.ok = true;
            args.RoutedEvent = LoadComplatedEvent;
            RaiseEvent(args);
        }

        #region 生成座標軸
        private async Task BeginGeneric()
        {
            await Task.Factory.StartNew(() =>
            {
                tempTimelineLabels.ForEach(item =>
                {
                    #region 生成點以及時間座標
                    var point = new TimelinePointControl();
                    var timelineLabelItem = new Lazy<Button>();
                    timelineLabelItem.Value.Style = timelineLabelStyle;
                    timelineLabelItem.Value.Content = item.TimelineLabelContent;
                    timelineLabelItem.Value.Name = getBtnLabelIndex(item);
                    timelineLabelItem.Value.Width = DefaultItemWidth;
                    timelinePoint.Children.Add(point);
                    switch (item.TimelineState)
                    {
                        case TimeLineEnum.TimelineLabelItemState.New:
                            timelineLabelItems.Children.Add(timelineLabelItem.Value);
                            break;
                        case TimeLineEnum.TimelineLabelItemState.Del:
                            var elements = timelineLabelItems.Children;
                            for (int i = 0; i < elements.Count; i++)
                            {
                                var btn = elements[i] as Button;
                                if (btn.Name.Equals(getBtnLabelIndex(item)))
                                    timelineLabelItems.Children.Remove(elements[i]);
                            }
                            break;
                        default:
                            var normalBtn = this.FindName(getBtnLabelIndex(item)) as Button;
                            if (null == normalBtn)
                                timelineLabelItems.Children.Add(timelineLabelItem.Value);
                            break;
                    }
                    #endregion
                });
            }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
        }
        #endregion

        #region 生成座標軸上事件
        private async Task GenericEvent()
        {
            await Task.Factory.StartNew(() =>
            {
                tempTimelineLabels.ForEach(item =>
                {
                    Console.WriteLine("有:" + TimelineEventSource.Count);
                    if (item.TimelineState != TimeLineEnum.TimelineLabelItemState.Del
                        && null != TimelineEventSource && TimelineEventSource.Count > 0)
                    {
                        Console.WriteLine("當前是第:" + currentIndexInBand + "個事件");
                        var e = new ObservableCollection<TimelineEventItem>(TimelineEventSource.Skip(currentIndexInBand));
                        var eventControl = new TimelineEventItemControl();
                        eventControl.ShowScatterEH += ((sender, eventArgs) =>
                        {
                            ShowScatterEventArgs args = new ShowScatterEventArgs();
                            args.svi = eventArgs.svi;
                            args.RoutedEvent = ShowScatterEvent;
                            RaiseEvent(args);
                        });
                        eventControl.ShowDetailEH += ((sender, eventArgs) =>
                        {
                            ShowDetailEventArgs args = new ShowDetailEventArgs();
                            args.startDate = eventArgs.startDate;
                            args.endDate = eventArgs.endDate;
                            args.showMode = eventArgs.showMode;
                            args.RoutedEvent = ShowDetailEvent;
                            RaiseEvent(args);
                        });
                        bool getEvent = false;
                        getEvent = TimelineEventGenericDictAction.Where(s => s.Key(item.TimelineType)).ForEach(s =>
                            s.Value(item, e, eventControl, getEvent))[0];
                        Console.WriteLine("拿到事件:" + getEvent);
                        if (!getEvent)
                        {
                            var o = new TimelineEventItem();
                            o.EventType = TimelineEventEnum.TimelineEventType.None;
                            eventControl.DataContext = o;
                            timelineEventItems.Children.Add(eventControl);
                        }
                        else
                            getEvent = false;
                    }
                });
            }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
        }
        #endregion

        private static string getBtnLabelIndex(TimelineLabelItem item)
        {
            return "index" + item.TimelineDate.Year.ToString()
                    + item.TimelineDate.Month.ToString()
                    + item.TimelineDate.Day.ToString();
        }

        public async Task<bool> doAnimation(bool o)
        {
            int key = 0;
            if (o) key = 1;
            return await Task.Factory.StartNew<bool>(() =>
            {
                for (int i = 0; i < timelineLabelItems.Children.Count; i++)
                {
                    (timelinePoint.Children[i] as UserControl).DataContext = key;
                    (timelineLabelItems.Children[i] as Button).DataContext = key;
                }
                for (int i = 0; i < timelineEventItems.Children.Count; i++)
                {
                    (timelineEventItems.Children[i] as UserControl).DataContext = key;
                }
                return true;
            }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
        }

        #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
    }
}


 

發佈了38 篇原創文章 · 獲贊 35 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章