[TemplatePart(Name = A_PARTNAME, Type = typeof(Border))] [TemplatePart(Name = B_PARTNAME, Type = typeof(Border))] [TemplatePart(Name = C_PARTNAME, Type = typeof(Border))] [TemplatePart(Name = D_PARTNAME, Type = typeof(Border))] [TemplatePart(Name = E_PARTNAME, Type = typeof(Border))] [TemplatePart(Name = F_PARTNAME, Type = typeof(Border))] [TemplatePart(Name = A_RECT_PARTNAME, Type = typeof(RectangleGeometry))] [TemplatePart(Name = B_RECT_PARTNAME, Type = typeof(RectangleGeometry))] [TemplatePart(Name = C_RECT_PARTNAME, Type = typeof(RectangleGeometry))] [TemplatePart(Name = D_RECT_PARTNAME, Type = typeof(RectangleGeometry))] [TemplatePart(Name = E_RECT_PARTNAME, Type = typeof(RectangleGeometry))] [TemplatePart(Name = F_RECT_PARTNAME, Type = typeof(RectangleGeometry))] [TemplatePart(Name = A_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = B_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = C_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = D_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = E_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = F_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = A_PRESENTER_PARTNAME, Type = typeof(ContentPresenter))] [TemplatePart(Name = B_PRESENTER_PARTNAME, Type = typeof(ContentPresenter))] [TemplatePart(Name = C_PRESENTER_PARTNAME, Type = typeof(ContentPresenter))] [TemplatePart(Name = D_PRESENTER_PARTNAME, Type = typeof(ContentPresenter))] [TemplatePart(Name = E_PRESENTER_PARTNAME, Type = typeof(ContentPresenter))] [TemplatePart(Name = F_PRESENTER_PARTNAME, Type = typeof(ContentPresenter))] [TemplatePart(Name = INNER_LEFT_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = OUTER_LEFT_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = INNER_RIGHT_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = OUTER_RIGHT_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = MARGIN_LEFT_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = MARGIN_RIGHT_TRANS_PARTNAME, Type = typeof(CompositeTransform))] [TemplatePart(Name = ST_SHADOW_SPLIT_INNER_LEFT_PARTNAME, Type = typeof(StackPanel))] [TemplatePart(Name = ST_SHADOW_SPLIT_OUTER_LEFT_PARTNAME, Type = typeof(StackPanel))] [TemplatePart(Name = ST_SHADOW_SPLIT_INNER_RIGHT_PARTNAME, Type = typeof(StackPanel))] [TemplatePart(Name = ST_SHADOW_SPLIT_OUTER_RIGHT_PARTNAME, Type = typeof(StackPanel))] [TemplatePart(Name = ST_SHADOW_MARGIN_LEFT_PARTNAME, Type = typeof(StackPanel))] [TemplatePart(Name = ST_SHADOW_MARGIN_RIGHT_PARTNAME, Type = typeof(StackPanel))] [TemplatePart(Name = BOOK_CONTAINER_PARTNAME, Type = typeof(Image))] [TemplatePart(Name = GRD_CONTENT_PARTNAME, Type = typeof(Grid))] /// <summary> /// 作者:王韧竹 /// 版本:1.1 /// 根据偏移量算法 计算是否为放大 或者翻页 保证两者不冲突。 /// 18/6/2013 23:06 /// windows8 翻书特效组件 /// </summary> public sealed class FlipBookControl : ItemsControl { #region Member Variables /// <summary> /// 0 初始 翻页状态1 翻页状态2 /// </summary> private int Status = 0; /// <summary> /// 是否翻下一页 /// true 下一页 false 上一页 /// </summary> private bool isNext = false; /// <summary> /// 触发向左翻页动画 /// true 发生偏移 false 停止偏移 /// </summary> private bool turnLeft = false; /// <summary> /// 触发向右翻页动画 /// true 发生偏移 false 停止偏移 /// </summary> private bool turnRight = false; /// <summary> /// 触发向右翻页还原动画 /// true 发生偏移 false 停止偏移 /// </summary> private bool rightRestore = false; /// <summary> /// 触发向左翻页还原动画 /// true 发生偏移 false 停止偏移 /// </summary> private bool leftRestore = false; /// <summary> /// 是否多点操作中 /// true 是 false 否 /// </summary> private bool isManipulating = false; /// <summary> /// 最近一次偏移量 /// </summary> private double lastDeltaOffset = 0.0; /// <summary> /// 横向偏移量 /// </summary> private double offsetWidth = 0.0; /// <summary> /// 竖向偏移量 /// </summary> private double offsetHeight = 0.0; /// <summary> /// 是否加载 /// </summary> private bool isLoaded = false; /// <summary> /// 是否初始化 /// </summary> private bool isInit = false; /// <summary> /// 控制是否翻页 /// </summary> private bool isFlip = true; /// <summary> /// 是否释放 /// </summary> private bool isRelease = true; Border nextPage; Border prevPage; Border leftPage; Border rightPage; Border leftTopPage; Border rightTopPage; CompositeTransform nextTrans; CompositeTransform prevTrans; Border A; Border B; Border C; Border D; Border E; Border F; ContentPresenter APresenter; ContentPresenter BPresenter; ContentPresenter CPresenter; ContentPresenter DPresenter; ContentPresenter EPresenter; ContentPresenter FPresenter; RectangleGeometry ARect; RectangleGeometry BRect; RectangleGeometry CRect; RectangleGeometry DRect; RectangleGeometry ERect; RectangleGeometry FRect; CompositeTransform transA; CompositeTransform transB; CompositeTransform transC; CompositeTransform transD; CompositeTransform transE; CompositeTransform transF; CompositeTransform innerLeftTrans; CompositeTransform outerLeftTrans; CompositeTransform innerRightTrans; CompositeTransform outerRightTrans; CompositeTransform marginLeftTrans; CompositeTransform marginRightTrans; StackPanel stShadowSplitOuterLeft; StackPanel stShadowSplitInnerLeft; StackPanel stShadowSplitOuterRight; StackPanel stShadowSplitInnerRight; StackPanel stShadowMarginLeft; StackPanel stShadowMarginRight; Grid grdContent; Image bookContainer; ImageBrush leftBrush; ImageBrush rightBrush; private TransformGroup _transformGroup; private MatrixTransform _previousTransform; private CompositeTransform _compositeTransform; #endregion #region Template Part /// <summary> /// 矩形 /// </summary> const string A_PARTNAME = "A"; /// <summary> /// 矩形遮掩 /// </summary> const string A_RECT_PARTNAME = "ARect"; /// <summary> /// 矩形偏移 /// </summary> const string A_TRANS_PARTNAME = "transA"; const string A_PRESENTER_PARTNAME = "APresenter"; const string B_PARTNAME = "B"; const string B_RECT_PARTNAME = "BRect"; const string B_TRANS_PARTNAME = "transB"; const string B_PRESENTER_PARTNAME = "BPresenter"; const string C_PARTNAME = "C"; const string C_RECT_PARTNAME = "CRect"; const string C_TRANS_PARTNAME = "transC"; const string C_PRESENTER_PARTNAME = "CPresenter"; const string D_PARTNAME = "D"; const string D_RECT_PARTNAME = "DRect"; const string D_TRANS_PARTNAME = "transD"; const string D_PRESENTER_PARTNAME = "DPresenter"; const string E_PARTNAME = "E"; const string E_RECT_PARTNAME = "ERect"; const string E_TRANS_PARTNAME = "transE"; const string E_PRESENTER_PARTNAME = "EPresenter"; const string F_PARTNAME = "F"; const string F_RECT_PARTNAME = "FRect"; const string F_TRANS_PARTNAME = "transF"; const string F_PRESENTER_PARTNAME = "FPresenter"; const string ST_SHADOW_SPLIT_OUTER_RIGHT_PARTNAME = "stShadowSplitOuterRight"; const string ST_SHADOW_SPLIT_INNER_RIGHT_PARTNAME = "stShadowSplitInnerRight"; const string ST_SHADOW_SPLIT_OUTER_LEFT_PARTNAME = "stShadowSplitOuterLeft"; const string ST_SHADOW_SPLIT_INNER_LEFT_PARTNAME = "stShadowSplitInnerLeft"; const string ST_SHADOW_MARGIN_LEFT_PARTNAME = "stShadowMarginLeft"; const string ST_SHADOW_MARGIN_RIGHT_PARTNAME = "stShadowMarginRight"; const string OUTER_LEFT_TRANS_PARTNAME = "outerLeftTrans"; const string INNER_LEFT_TRANS_PARTNAME = "innerLeftTrans"; const string OUTER_RIGHT_TRANS_PARTNAME = "outerRightTrans"; const string INNER_RIGHT_TRANS_PARTNAME = "innerRightTrans"; const string MARGIN_LEFT_TRANS_PARTNAME = "marginLeftTrans"; const string MARGIN_RIGHT_TRANS_PARTNAME = "marginRightTrans"; /// <summary> /// 书壳 /// </summary> const string BOOK_CONTAINER_PARTNAME = "bookContainer"; const string GRD_CONTENT_PARTNAME = "grdContent"; #endregion #region DependencyProperties #region DelayLoad public TimeSpan DelayLoad { get { return (TimeSpan)GetValue(DelayLoadProperty); } set { SetValue(DelayLoadProperty, value); } } // Using a DependencyProperty as the backing store for DelayLoad. This enables animation, styling, binding, etc... public static readonly DependencyProperty DelayLoadProperty = DependencyProperty.Register("DelayLoad", typeof(TimeSpan), typeof(FlipBookControl), new PropertyMetadata(TimeSpan.FromSeconds(0))); #endregion #region BookBackgroundBrush public ImageBrush BookBackgroundBrush { get { return (ImageBrush)GetValue(BookBackgroundBrushProperty); } set { SetValue(BookBackgroundBrushProperty, value); } } // Using a DependencyProperty as the backing store for BookBackgroundBrush. This enables animation, styling, binding, etc... public static readonly DependencyProperty BookBackgroundBrushProperty = DependencyProperty.Register("BookBackgroundBrush", typeof(ImageBrush), typeof(FlipBookControl), new PropertyMetadata(null, OnBookBackgroundBrushChangedCallBack)); private static async void OnBookBackgroundBrushChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctrl = (d as FlipBookControl); if (ctrl.isLoaded) await ctrl.GetCropBrush(); } #endregion #region Speed /// <summary> /// 动画速度 默认为30pixel /// </summary> public int Speed { get { return (int)GetValue(SpeedProperty); } set { SetValue(SpeedProperty, value); } } // Using a DependencyProperty as the backing store for Speed. This enables animation, styling, binding, etc... public static readonly DependencyProperty SpeedProperty = DependencyProperty.Register("Speed", typeof(int), typeof(FlipBookControl), new PropertyMetadata(30)); #endregion #region BookContainerSource public ImageSource BookContainerSource { get { return (ImageSource)GetValue(BookContainerSourceProperty); } set { SetValue(BookContainerSourceProperty, value); } } // Using a DependencyProperty as the backing store for BookContainerSource. This enables animation, styling, binding, etc... public static readonly DependencyProperty BookContainerSourceProperty = DependencyProperty.Register("BookContainerSource", typeof(ImageSource), typeof(FlipBookControl), new PropertyMetadata(null, OnBookContainerSourceChangedCallBack)); private static void OnBookContainerSourceChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctrl = (d as FlipBookControl); if (null != ctrl.BookContainerSource && ctrl.bookContainer != null && ctrl.isLoaded) ctrl.bookContainer.Source = ctrl.BookContainerSource; } #endregion #region PageIndex public int PageIndex { get { return (int)GetValue(PageIndexProperty); } set { SetValue(PageIndexProperty, value); } } // Using a DependencyProperty as the backing store for PageIndex. This enables animation, styling, binding, etc... public static readonly DependencyProperty PageIndexProperty = DependencyProperty.Register("PageIndex", typeof(int), typeof(FlipBookControl), new PropertyMetadata(0, OnPageIndexChangedCallBack)); private static void OnPageIndexChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctrl = (d as FlipBookControl); if (ctrl.isLoaded) { var isNext = Convert.ToInt32(e.NewValue) > Convert.ToInt32(e.OldValue); var presenters = ctrl.GetPresentersByPageIndex(isNext); if (null != presenters) ctrl.LoadPageContentByPageIndex(Convert.ToInt32(e.NewValue), isNext, presenters[0], presenters[1]); } } #endregion #region DisposeAction public Action<object> DisposeAction { get { return (Action<object>)GetValue(DisposeActionProperty); } set { SetValue(DisposeActionProperty, value); } } // Using a DependencyProperty as the backing store for DisposeAction. This enables animation, styling, binding, etc... public static readonly DependencyProperty DisposeActionProperty = DependencyProperty.Register("DisposeAction", typeof(Action<object>), typeof(FlipBookControl), new PropertyMetadata(null)); #endregion #region RestoreItemAction public Action<object> RestoreItemAction { get { return (Action<object>)GetValue(RestoreItemActionProperty); } set { SetValue(RestoreItemActionProperty, value); } } // Using a DependencyProperty as the backing store for RestoreItemAction. This enables animation, styling, binding, etc... public static readonly DependencyProperty RestoreItemActionProperty = DependencyProperty.Register("RestoreItemAction", typeof(Action<object>), typeof(FlipBookControl), new PropertyMetadata(null)); #endregion #region CanScale public bool CanScale { get { return (bool)GetValue(CanScaleProperty); } set { SetValue(CanScaleProperty, value); } } // 能否进行放大缩小 public static readonly DependencyProperty CanScaleProperty = DependencyProperty.Register("CanScale", typeof(bool), typeof(FlipBookControl), new PropertyMetadata(false)); #endregion #endregion #region Event /// <summary> /// 翻书结束事件 /// </summary> private delegate void Fliped(object sender, FlipEventArgs args); private event Fliped Fliping; /// <summary> /// 加载事件 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> public delegate void NeedLoadItems(object sender, FlipLoadArgs args); public event NeedLoadItems NeedLoadingItem; #endregion #region Constructor public FlipBookControl() { this.DefaultStyleKey = typeof(FlipBookControl); this.Loaded += FlipBookControlLoaded; this.Unloaded += FlipBookControlUnLoaded; CompositionTarget.Rendering += RenderAnimation; this.Fliping += FlipEnded; } /// <summary> /// 初始化完毕开始载入数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void FlipBookControlLoaded(object sender, RoutedEventArgs e) { grdContent.ManipulationMode = ManipulationModes.TranslateInertia | ManipulationModes.TranslateX | ManipulationModes.Scale | ManipulationModes.ScaleInertia | ManipulationModes.TranslateY; grdContent.ManipulationDelta += FlipManipulationDelta; grdContent.ManipulationCompleted += FlipManipulationCompleted; grdContent.ManipulationStarting += FlipManipulationStarting; grdContent.ManipulationInertiaStarting += FlipManipulationInertiaStarting; A.PointerPressed += PointerPressed; B.PointerPressed += PointerPressed; C.PointerPressed += PointerPressed; D.PointerPressed += PointerPressed; E.PointerPressed += PointerPressed; F.PointerPressed += PointerPressed; offsetWidth = A.ActualWidth; offsetHeight = A.ActualHeight; await GetCropBrush(); bookContainer.Source = BookContainerSource; RefreshPageByStatus(); InitPages(); isLoaded = true; } private void FlipBookControlUnLoaded(object sender, RoutedEventArgs e) { CompositionTarget.Rendering -= RenderAnimation; grdContent.ManipulationDelta -= FlipManipulationDelta; grdContent.ManipulationCompleted -= FlipManipulationCompleted; grdContent.ManipulationStarting -= FlipManipulationStarting; grdContent.ManipulationInertiaStarting -= FlipManipulationInertiaStarting; this.Fliping -= FlipEnded; A.PointerPressed -= PointerPressed; B.PointerPressed -= PointerPressed; C.PointerPressed -= PointerPressed; D.PointerPressed -= PointerPressed; E.PointerPressed -= PointerPressed; F.PointerPressed -= PointerPressed; } public void InitPosition() { _compositeTransform = new CompositeTransform(); _previousTransform = new MatrixTransform() { Matrix = Matrix.Identity }; _transformGroup = new TransformGroup(); _transformGroup.Children.Add(_previousTransform); _transformGroup.Children.Add(_compositeTransform); this.RenderTransform = _transformGroup; } public async void InitPages() { if (!isInit && PageIndex == 0 && this.Items.Count > 0) { await Task.Delay(DelayLoad); List<object> needLoadItems = new List<object>(); //第一次加载 载入4页 CPresenter.DataContext = this.Items[0]; needLoadItems.Add(Items[0]); if (this.Items.Count > 1) { DPresenter.DataContext = this.Items[1]; needLoadItems.Add(Items[1]); } if (this.Items.Count > 2) { EPresenter.DataContext = this.Items[2]; needLoadItems.Add(Items[2]); } if (this.Items.Count > 3) { FPresenter.DataContext = this.Items[3]; needLoadItems.Add(Items[3]); } if (null != NeedLoadingItem) NeedLoadingItem(this, new FlipLoadArgs(needLoadItems, false)); isInit = true; } else { Status = 0; this.PageIndex = 0; if (null != APresenter) { APresenter.DataContext = null; BPresenter.DataContext = null; CPresenter.DataContext = null; DPresenter.DataContext = null; EPresenter.DataContext = null; FPresenter.DataContext = null; } } InitPosition(); } #endregion #region EventMethod #region OnApplyTemplate protected override void OnApplyTemplate() { bookContainer = GetTemplateChild(BOOK_CONTAINER_PARTNAME) as Image; A = GetTemplateChild(A_PARTNAME) as Border; B = GetTemplateChild(B_PARTNAME) as Border; C = GetTemplateChild(C_PARTNAME) as Border; D = GetTemplateChild(D_PARTNAME) as Border; E = GetTemplateChild(E_PARTNAME) as Border; F = GetTemplateChild(F_PARTNAME) as Border; APresenter = GetTemplateChild(A_PRESENTER_PARTNAME) as ContentPresenter; BPresenter = GetTemplateChild(B_PRESENTER_PARTNAME) as ContentPresenter; CPresenter = GetTemplateChild(C_PRESENTER_PARTNAME) as ContentPresenter; DPresenter = GetTemplateChild(D_PRESENTER_PARTNAME) as ContentPresenter; EPresenter = GetTemplateChild(E_PRESENTER_PARTNAME) as ContentPresenter; FPresenter = GetTemplateChild(F_PRESENTER_PARTNAME) as ContentPresenter; ARect = GetTemplateChild(A_RECT_PARTNAME) as RectangleGeometry; BRect = GetTemplateChild(B_RECT_PARTNAME) as RectangleGeometry; CRect = GetTemplateChild(C_RECT_PARTNAME) as RectangleGeometry; DRect = GetTemplateChild(D_RECT_PARTNAME) as RectangleGeometry; ERect = GetTemplateChild(E_RECT_PARTNAME) as RectangleGeometry; FRect = GetTemplateChild(F_RECT_PARTNAME) as RectangleGeometry; transA = GetTemplateChild(A_TRANS_PARTNAME) as CompositeTransform; transB = GetTemplateChild(B_TRANS_PARTNAME) as CompositeTransform; transC = GetTemplateChild(C_TRANS_PARTNAME) as CompositeTransform; transD = GetTemplateChild(D_TRANS_PARTNAME) as CompositeTransform; transE = GetTemplateChild(E_TRANS_PARTNAME) as CompositeTransform; transF = GetTemplateChild(F_TRANS_PARTNAME) as CompositeTransform; grdContent = GetTemplateChild(GRD_CONTENT_PARTNAME) as Grid; innerLeftTrans = GetTemplateChild(INNER_LEFT_TRANS_PARTNAME) as CompositeTransform; outerLeftTrans = GetTemplateChild(OUTER_LEFT_TRANS_PARTNAME) as CompositeTransform; innerRightTrans = GetTemplateChild(INNER_RIGHT_TRANS_PARTNAME) as CompositeTransform; outerRightTrans = GetTemplateChild(OUTER_RIGHT_TRANS_PARTNAME) as CompositeTransform; marginLeftTrans = GetTemplateChild(MARGIN_LEFT_TRANS_PARTNAME) as CompositeTransform; marginRightTrans = GetTemplateChild(MARGIN_RIGHT_TRANS_PARTNAME) as CompositeTransform; stShadowSplitInnerLeft = GetTemplateChild(ST_SHADOW_SPLIT_INNER_LEFT_PARTNAME) as StackPanel; stShadowSplitOuterLeft = GetTemplateChild(ST_SHADOW_SPLIT_OUTER_LEFT_PARTNAME) as StackPanel; stShadowSplitInnerRight = GetTemplateChild(ST_SHADOW_SPLIT_INNER_RIGHT_PARTNAME) as StackPanel; stShadowSplitOuterRight = GetTemplateChild(ST_SHADOW_SPLIT_OUTER_RIGHT_PARTNAME) as StackPanel; stShadowMarginLeft = GetTemplateChild(ST_SHADOW_MARGIN_LEFT_PARTNAME) as StackPanel; stShadowMarginRight = GetTemplateChild(ST_SHADOW_MARGIN_RIGHT_PARTNAME) as StackPanel; base.OnApplyTemplate(); } #endregion #region PointerPressed /// <summary> /// 确定翻页方向 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void PointerPressed(object sender, PointerRoutedEventArgs e) { if (!isManipulating) { if (sender.Equals(leftPage)) isNext = false; else if (sender.Equals(rightPage)) isNext = true; else RefreshPageByStatus(); Debug.WriteLine("按下:" + isNext); Debug.WriteLine("点击的壳:" + (sender as Border).Name + " 左页壳:" + (sender as Border).Name); } } #endregion #region OnPointerReleased protected override void OnPointerReleased(PointerRoutedEventArgs e) { base.OnPointerReleased(e); } #endregion #region FlipEnded /// <summary> /// 翻页完毕 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private async void FlipEnded(object sender, FlipEventArgs args) { Debug.WriteLine("翻页完毕:" + args.isNext); if (args.isNext) PageIndex += 2; else PageIndex -= 2; await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => RefreshPageByStatus()); } #endregion #region Manipulation 多点触控操作翻书特效 #region FlipManipulationStarting private void FlipManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e) { isManipulating = true; e.Handled = true; if (isNext) { if (PageIndex >= this.Items.Count - 2) { isFlip = false; isManipulating = false; } } else { if (this.PageIndex == 0) { isFlip = false; isManipulating = false; } } } #endregion #region FlipManipulationInertiaStarting private void FlipManipulationInertiaStarting(object sender, ManipulationInertiaStartingRoutedEventArgs e) { e.TranslationBehavior.DesiredDeceleration = 5 * 96.0 / (1000.0 * 1000.0); e.ExpansionBehavior.DesiredDeceleration = 100 * 96 / 1000.0 * 1000.0; } #endregion #region FlipManipulationCompleted private async void FlipManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) { isManipulating = false; if (isFlip) { IsHitVisible(false); var leftTopOffset = leftTopPage.Clip.Rect.X; var rightTopOffset = rightTopPage.Clip.Rect.X; await Task.Run(() => { if (isNext) { if (lastDeltaOffset < 0) { Status = Status < 2 ? Status + 1 : 0; turnRight = true; } else if (rightTopOffset != 0.0) rightRestore = true; else IsHitVisible(true); Debug.WriteLine("下一页:" + turnRight); } else { if (lastDeltaOffset > 0) { Status = Status > 0 ? Status - 1 : 2; turnLeft = true; } else if (leftTopOffset != 0.0) leftRestore = true; else IsHitVisible(true); Debug.WriteLine("上一页" + turnLeft); } }); Debug.WriteLine("翻页状态:" + Status); } isFlip = true; CanScale = false; } #endregion #region FlipManipulationDelta private void FlipManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) { var scale = e.Delta.Scale; var translateX = e.Delta.Translation.X; var translateY = e.Delta.Translation.Y; var nTtranX = nextTrans.TranslateX; var nTtranY = nextTrans.TranslateY; var ctranlateX = e.Cumulative.Translation.X; var ctranlateY = e.Cumulative.Translation.Y; CanScale = Task.Run(() => { if (scale != 1.0 || (Math.Abs(ctranlateX * 1.15) < Math.Abs(ctranlateY))) return true; else return false; }).Result; if (isManipulating && !CanScale) { if (isNext) { #region 下一页 var rightTopNect = rightTopPage.Clip.Rect; var nextRect = nextPage.Clip.Rect; var nextTransOffset = nTtranX + translateX * 2; SetShadowOperacity(Math.Abs(nextTransOffset), offsetWidth, false); var nextRectXOffset = nextRect.X - e.Delta.Translation.X; lastDeltaOffset = e.Delta.Translation.X; if (nextRectXOffset < 0 && nextRectXOffset > -offsetWidth) { outerRightTrans.TranslateX += e.Delta.Translation.X; innerRightTrans.TranslateX += e.Delta.Translation.X; marginRightTrans.TranslateX += e.Delta.Translation.X * 2; nextTrans.TranslateX = nextTransOffset; if (nextRectXOffset < 0) nextRect.X = nextRectXOffset; rightTopNect.X += e.Delta.Translation.X; nextPage.Clip.Rect = nextRect; rightTopPage.Clip.Rect = rightTopNect; } else { e.Complete(); if (nextTransOffset < 0) { nextTrans.TranslateX = -offsetWidth; nextRect.X = 0; rightTopNect.X = 0; nextPage.Clip.Rect = nextRect; rightTopPage.Clip.Rect = rightTopNect; } else { nextTrans.TranslateX = offsetWidth; nextRect.X = -offsetWidth; rightTopNect.X = offsetWidth; nextPage.Clip.Rect = nextRect; rightTopPage.Clip.Rect = rightTopNect; } } #endregion } else { #region 上一页 var leftTopNect = leftTopPage.Clip.Rect; var prevRect = prevPage.Clip.Rect; var prevTransOffset = prevTrans.TranslateX + e.Delta.Translation.X * 2; var prevRectXOffset = prevRect.X - e.Delta.Translation.X; SetShadowOperacity(Math.Abs(prevTransOffset), offsetWidth, true); lastDeltaOffset = e.Delta.Translation.X; if (prevRectXOffset > 0 && prevRectXOffset < offsetWidth) { innerLeftTrans.TranslateX += translateX; outerLeftTrans.TranslateX += translateX; marginLeftTrans.TranslateX += translateX * 2; prevTrans.TranslateX = prevTransOffset; if (prevRectXOffset > 0) prevRect.X = prevRectXOffset; leftTopNect.X += e.Delta.Translation.X; prevPage.Clip.Rect = prevRect; leftTopPage.Clip.Rect = leftTopNect; } else { e.Complete(); if (prevTransOffset < 0) { prevTrans.TranslateX = -offsetWidth; prevRect.X = offsetWidth; leftTopNect.X = -offsetWidth; prevPage.Clip.Rect = prevRect; leftTopPage.Clip.Rect = leftTopNect; } else { prevTrans.TranslateX = offsetWidth; prevRect.X = 0; leftTopNect.X = 0; prevPage.Clip.Rect = prevRect; leftTopPage.Clip.Rect = leftTopNect; } } #endregion } } if (CanScale) { _previousTransform.Matrix = _transformGroup.Value; Point center = _previousTransform.TransformPoint(new Point(e.Position.X, e.Position.Y)); _compositeTransform.CenterX = center.X; _compositeTransform.CenterY = center.Y; _compositeTransform.ScaleX = e.Delta.Scale; _compositeTransform.ScaleY = e.Delta.Scale; _compositeTransform.TranslateX = e.Delta.Translation.X; _compositeTransform.TranslateY = e.Delta.Translation.Y; } } #endregion #endregion #region RenderAnimation 绘制翻页动画 private void RenderAnimation(object sender, object e) { if (turnLeft) { rightRestore = false; turnRight = false; var prevRect = prevPage.Clip.Rect; var leftTopRect = leftTopPage.Clip.Rect; var prevOffset = prevRect.X - Speed / 2; if (prevOffset > 0) { prevRect.X = prevOffset; prevTrans.TranslateX += Speed; leftTopRect.X += Speed / 2; innerLeftTrans.TranslateX += Speed / 2; outerLeftTrans.TranslateX += Speed / 2; marginLeftTrans.TranslateX += Speed; SetShadowOperacity(Math.Abs(prevTrans.TranslateX), offsetWidth, true); } else { prevRect.X = 0; leftTopRect.X = 0; turnLeft = false; prevTrans.TranslateX = offsetWidth; Fliping(sender, new FlipEventArgs(false)); } prevPage.Clip.Rect = prevRect; leftTopPage.Clip.Rect = leftTopRect; IsHitVisible(true); } else if (leftRestore) { turnLeft = false; turnRight = false; rightRestore = false; var prevRect = prevPage.Clip.Rect; var leftTopRect = leftTopPage.Clip.Rect; var prevOffset = prevRect.X + Speed / 2; if (prevOffset < offsetWidth) { prevRect.X = prevOffset; prevTrans.TranslateX -= Speed; leftTopRect.X -= Speed / 2; innerLeftTrans.TranslateX -= Speed / 2; outerLeftTrans.TranslateX -= Speed / 2; marginLeftTrans.TranslateX -= Speed; SetShadowOperacity(Math.Abs(prevTrans.TranslateX), offsetWidth, true); } else { prevRect.X = offsetWidth; leftTopRect.X = -offsetWidth; prevTrans.TranslateX = -offsetWidth; innerLeftTrans.TranslateX = 0; outerLeftTrans.TranslateX = 0; marginLeftTrans.TranslateX = 0; leftRestore = false; } prevPage.Clip.Rect = prevRect; leftTopPage.Clip.Rect = leftTopRect; IsHitVisible(true); } else if (turnRight) { rightRestore = false; turnLeft = false; var nextRect = nextPage.Clip.Rect; var rightTopRect = rightTopPage.Clip.Rect; var nextOffset = nextRect.X + Speed / 2; if (nextOffset < 0) { nextRect.X = nextOffset; nextTrans.TranslateX -= Speed; rightTopRect.X -= Speed / 2; innerRightTrans.TranslateX -= Speed / 2; outerRightTrans.TranslateX -= Speed / 2; marginRightTrans.TranslateX -= Speed; SetShadowOperacity(Math.Abs(nextTrans.TranslateX), offsetWidth, false); } else { nextRect.X = 0; nextTrans.TranslateX = -offsetWidth; turnRight = false; rightTopRect.X = 0; Fliping(sender, new FlipEventArgs(true)); } nextPage.Clip.Rect = nextRect; rightTopPage.Clip.Rect = rightTopRect; IsHitVisible(true); } else if (rightRestore) { turnRight = false; turnLeft = false; leftRestore = false; var nextRect = nextPage.Clip.Rect; var rightTopRect = rightTopPage.Clip.Rect; var nextOffset = nextRect.X - Speed / 2; if (nextRect.X - Speed / 2 > -offsetWidth) { nextRect.X = nextOffset; nextTrans.TranslateX += Speed; rightTopRect.X += Speed / 2; innerRightTrans.TranslateX += Speed / 2; outerRightTrans.TranslateX += Speed / 2; marginRightTrans.TranslateX += Speed; SetShadowOperacity(Math.Abs(nextTrans.TranslateX), offsetWidth, false); } else { nextRect.X = -offsetWidth; rightTopRect.X = offsetWidth; nextTrans.TranslateX = offsetWidth; innerRightTrans.TranslateX = 0; outerRightTrans.TranslateX = 0; marginRightTrans.TranslateX = 0; rightRestore = false; } rightTopPage.Clip.Rect = rightTopRect; nextPage.Clip.Rect = nextRect; IsHitVisible(true); } } #endregion #endregion #region Method #region LoadPageContentByPageIndex private void LoadPageContentByPageIndex(int PageIndex, bool isNextOrPrev, ContentPresenter firstPresenter, ContentPresenter secondPresenter) { List<object> needLoadItems = new List<object>(); if (isNextOrPrev) { //加载下一页模板 if (PageIndex + 2 < this.Items.Count) { firstPresenter.Content = null; firstPresenter.DataContext = null; object item = null; if (this.Items.Count > PageIndex + 2) { item = this.Items[PageIndex + 2]; needLoadItems.Add(item); firstPresenter.DataContext = item; } } else firstPresenter.DataContext = null; if (PageIndex + 3 < this.Items.Count) { object item = null; secondPresenter.Content = null; secondPresenter.DataContext = null; if (this.Items.Count > PageIndex + 3) { item = this.Items[PageIndex + 3]; needLoadItems.Add(item); secondPresenter.DataContext = item; } } else secondPresenter.DataContext = null; if (null != NeedLoadingItem) NeedLoadingItem(this, new FlipLoadArgs(needLoadItems, true)); RecycleData(true, needLoadItems); } else { if (PageIndex - 2 >= 0 && Items.Count > PageIndex - 2) { needLoadItems.Add(this.Items[PageIndex - 2]); secondPresenter.Content = null; secondPresenter.DataContext = null; secondPresenter.DataContext = this.Items[PageIndex - 2]; } if (PageIndex - 1 >= 0 && Items.Count > PageIndex - 1) { firstPresenter.Content = null; firstPresenter.DataContext = null; firstPresenter.DataContext = this.Items[PageIndex - 1]; needLoadItems.Add(this.Items[PageIndex - 1]); } //加载上一页模板 if (null != NeedLoadingItem) NeedLoadingItem(this, new FlipLoadArgs(needLoadItems, false)); RecycleData(false, needLoadItems); } } #endregion #region RecycleData private async void RecycleData(bool isNext, List<object> needItems) { await Task.Run(async () => { foreach (var o in needItems) { await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { if (null != this.RestoreItemAction) this.RestoreItemAction.Invoke(o); }); } if (isNext) { var index = -1; try { index = this.Items.IndexOf(needItems[0]); } catch { index = -1; } if (index != -1 && index - 8 > 0) { for (int i = index - 8; i < index - 6; i++) await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { if (null != this.DisposeAction) DisposeAction.Invoke(this.Items[i]); }); } } else { var index = -1; try { index = this.Items.IndexOf(needItems.Last()); } catch (Exception ex) { index = -1; } if (index != -1 && this.Items.Count > index + 7) { for (int i = index + 5; i < index + 7; i++) await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { if (null != this.DisposeAction) DisposeAction.Invoke(this.Items[i]); }); } } }); } #endregion #region OnItemsChanged /// <summary> /// 刷新数据 /// </summary> /// <param name="e"></param> protected override void OnItemsChanged(object e) { isInit = false; InitPages(); base.OnItemsChanged(e); } #endregion #region GetPresentersByPageIndex private List<ContentPresenter> GetPresentersByPageIndex(bool isNext) { List<ContentPresenter> presenters = new List<ContentPresenter>(); if (isNext) { presenters.Add(leftTopPage.Child as ContentPresenter); presenters.Add(prevPage.Child as ContentPresenter); } else { presenters.Add(rightTopPage.Child as ContentPresenter); presenters.Add(nextPage.Child as ContentPresenter); } Debug.WriteLine("presenter0Name:" + presenters[0].Name); Debug.WriteLine("presenter1Name:" + presenters[1].Name); return presenters; } #endregion #region Crop /// <summary> /// 图形切割 /// </summary> /// <param name="source"></param> /// <param name="x1"></param> /// <param name="y1"></param> /// <param name="x2"></param> /// <param name="y2"></param> /// <returns></returns> public WriteableBitmap Crop(WriteableBitmap source, int x1, int y1, int x2, int y2) { if (x1 >= x2 || y1 >= y2 || x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || x1 > source.PixelWidth || y1 > source.PixelHeight || x2 > source.PixelWidth || y2 > source.PixelHeight) { throw new ArgumentException(); } //var buffer = source.PixelBuffer.GetPixels(); var cw = x2 - x1; var ch = y2 - y1; var target = new WriteableBitmap(cw, ch); var croppedBytes = new byte[4 * cw * ch]; var inputStream = source.PixelBuffer.AsStream(); inputStream.Seek(4 * (source.PixelWidth * y1 + x1), SeekOrigin.Current); for (int i = 0; i < ch; i++) { inputStream.Read(croppedBytes, 4 * cw * i, 4 * cw); inputStream.Seek(4 * (source.PixelWidth - cw), SeekOrigin.Current); } var outputStream = target.PixelBuffer.AsStream(); outputStream.Seek(0, SeekOrigin.Begin); outputStream.Write(croppedBytes, 0, croppedBytes.Length); target.Invalidate(); return target; } #endregion #region IsHitVisible /// <summary> /// 禁止点击 /// </summary> /// <param name="o"></param> private async void IsHitVisible(bool o) { await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { this.grdContent.IsHitTestVisible = o; this.leftPage.IsHitTestVisible = o; this.rightPage.IsHitTestVisible = o; this.nextPage.IsHitTestVisible = o; this.prevPage.IsHitTestVisible = o; this.leftTopPage.IsHitTestVisible = o; this.rightTopPage.IsHitTestVisible = o; }); } #endregion #region RefreshPageByStatus /// <summary> /// 翻页成功后刷新控件状态 /// </summary> private void RefreshPageByStatus() { switch (Status) { case 0: Canvas.SetZIndex(A, 2); Canvas.SetZIndex(B, 2); Canvas.SetZIndex(C, 0); Canvas.SetZIndex(D, 0); Canvas.SetZIndex(E, 2); Canvas.SetZIndex(F, 2); Grid.SetColumn(A, 1); Grid.SetColumn(B, 1); Grid.SetColumn(C, 1); Grid.SetColumn(D, 2); Grid.SetColumn(E, 2); Grid.SetColumn(F, 2); transA.TranslateX = 0; transB.TranslateX = -offsetWidth; transC.TranslateX = 0; transD.TranslateX = 0; transE.TranslateX = offsetWidth; transF.TranslateX = 0; ARect.Rect = new Rect(-this.A.ActualWidth, 0, this.A.ActualWidth, this.A.ActualHeight); CRect.Rect = new Rect(0, 0, this.C.ActualWidth, this.C.ActualHeight); DRect.Rect = new Rect(0, 0, this.D.ActualWidth, this.D.ActualHeight); FRect.Rect = new Rect(this.F.ActualWidth, 0, this.F.ActualWidth, this.F.ActualHeight); BRect.Rect = new Rect(this.B.ActualWidth, 0, this.B.ActualWidth, this.B.ActualHeight); ERect.Rect = new Rect(-this.E.ActualWidth, 0, this.E.ActualWidth, this.E.ActualHeight); nextPage = E; prevPage = B; leftPage = C; rightPage = D; leftTopPage = A; rightTopPage = F; nextTrans = transE; prevTrans = transB; //A.PointerPressed -= this.PointerPressed; //B.PointerPressed -= this.PointerPressed; //C.PointerPressed += this.PointerPressed; //D.PointerPressed += this.PointerPressed; break; case 1: Canvas.SetZIndex(A, 2); Canvas.SetZIndex(B, 2); Canvas.SetZIndex(C, 2); Canvas.SetZIndex(D, 2); Canvas.SetZIndex(E, 0); Canvas.SetZIndex(F, 0); Grid.SetColumn(A, 2); Grid.SetColumn(B, 2); Grid.SetColumn(C, 1); Grid.SetColumn(D, 1); Grid.SetColumn(E, 1); Grid.SetColumn(F, 2); transA.TranslateX = offsetWidth; transB.TranslateX = 0; transC.TranslateX = 0; transD.TranslateX = -offsetWidth; transE.TranslateX = 0; transF.TranslateX = 0; ARect.Rect = new Rect(-this.A.ActualWidth, 0, this.A.ActualWidth, this.A.ActualHeight); CRect.Rect = new Rect(-this.C.ActualWidth, 0, this.C.ActualWidth, this.C.ActualHeight); DRect.Rect = new Rect(this.D.ActualWidth, 0, this.D.ActualWidth, this.D.ActualHeight); FRect.Rect = new Rect(0, 0, this.F.ActualWidth, this.F.ActualHeight); BRect.Rect = new Rect(this.B.ActualWidth, 0, this.B.ActualWidth, this.B.ActualHeight); ERect.Rect = new Rect(0, 0, this.E.ActualWidth, this.E.ActualHeight); nextPage = A; prevPage = D; leftPage = E; rightPage = F; leftTopPage = C; rightTopPage = B; nextTrans = transA; prevTrans = transD; //C.PointerPressed -= this.PointerPressed; //D.PointerPressed -= this.PointerPressed; //E.PointerPressed += this.PointerPressed; //F.PointerPressed += this.PointerPressed; break; case 2: Canvas.SetZIndex(A, 0); Canvas.SetZIndex(B, 0); Canvas.SetZIndex(C, 2); Canvas.SetZIndex(D, 2); Canvas.SetZIndex(E, 2); Canvas.SetZIndex(F, 2); Grid.SetColumn(A, 1); Grid.SetColumn(B, 2); Grid.SetColumn(C, 2); Grid.SetColumn(D, 2); Grid.SetColumn(E, 1); Grid.SetColumn(F, 1); transA.TranslateX = 0; transB.TranslateX = 0; transC.TranslateX = offsetWidth; transD.TranslateX = 0; transE.TranslateX = 0; transF.TranslateX = -offsetWidth; ARect.Rect = new Rect(0, 0, this.A.ActualWidth, this.A.ActualHeight); CRect.Rect = new Rect(-this.C.ActualWidth, 0, this.C.ActualWidth, this.C.ActualHeight); DRect.Rect = new Rect(this.D.ActualWidth, 0, this.D.ActualWidth, this.D.ActualHeight); FRect.Rect = new Rect(this.F.ActualWidth, 0, this.F.ActualWidth, this.F.ActualHeight); BRect.Rect = new Rect(0, 0, this.B.ActualWidth, this.B.ActualHeight); ERect.Rect = new Rect(-this.E.ActualWidth, 0, this.E.ActualWidth, this.E.ActualHeight); nextPage = C; prevPage = F; leftPage = A; rightPage = B; leftTopPage = E; rightTopPage = D; nextTrans = transC; prevTrans = transF; //E.PointerPressed -= this.PointerPressed; //F.PointerPressed -= this.PointerPressed; //A.PointerPressed += this.PointerPressed; //B.PointerPressed += this.PointerPressed; break; default: break; } stShadowSplitInnerLeft.Opacity = 0; stShadowSplitInnerRight.Opacity = 0; stShadowSplitOuterLeft.Opacity = 0; stShadowSplitOuterRight.Opacity = 0; outerRightTrans.TranslateX = 0; innerRightTrans.TranslateX = 0; outerLeftTrans.TranslateX = 0; innerLeftTrans.TranslateX = 0; marginLeftTrans.TranslateX = 0; marginRightTrans.TranslateX = 0; leftTopPage.Background = leftBrush; prevPage.Background = rightBrush; leftPage.Background = leftBrush; rightPage.Background = rightBrush; nextPage.Background = leftBrush; rightTopPage.Background = rightBrush; } #endregion #region GetCropBookBrush private async Task GetCropBrush() { if (null != this.BookBackgroundBrush) { var orginSource = this.BookBackgroundBrush.ImageSource as BitmapImage; if (!orginSource.UriSource.AbsolutePath.Equals(string.Empty)) { var uri = new Uri("ms-appx://" + orginSource.UriSource.AbsolutePath); try { var file = await StorageFile.GetFileFromApplicationUriAsync(uri); WriteableBitmap leftSource = new WriteableBitmap(Convert.ToInt32(offsetWidth * 2), Convert.ToInt32(offsetHeight)); await LoadAsync(leftSource, file); WriteableBitmap rightSource = new WriteableBitmap(Convert.ToInt32(offsetWidth * 2), Convert.ToInt32(offsetHeight)); await LoadAsync(rightSource, file); leftBrush = new ImageBrush(); rightBrush = new ImageBrush(); rightBrush.Stretch = Stretch.Fill; leftBrush.Stretch = Stretch.Fill; leftSource = Crop(leftSource, 0, 0, Convert.ToInt32(offsetWidth), Convert.ToInt32(offsetHeight)); leftBrush.ImageSource = leftSource; rightSource = Crop(rightSource, Convert.ToInt32(offsetWidth), 0, Convert.ToInt32(offsetWidth * 2), Convert.ToInt32(offsetHeight)); rightBrush.ImageSource = rightSource; } catch { } } } } #endregion #region LoadWriteableBitmap public async Task<WriteableBitmap> LoadAsync( WriteableBitmap writeableBitmap, StorageFile storageFile) { using (var stream = await storageFile.OpenReadAsync()) { await writeableBitmap.SetSourceAsync( stream); } return writeableBitmap; } #endregion #region SetShadowOperacity private async void SetShadowOperacity(double pos, double pageWidth, bool direction) { var opacity = await Task.Run(() => { double num = (pageWidth - pos) / 2.0; double num2 = Math.Abs((double)((pageWidth / 2.0) - num)); return (1.0 * (1.0 - (num2 / (pageWidth / 2.0)))); }); if (direction) { this.stShadowSplitOuterLeft.Opacity = opacity; this.stShadowSplitInnerLeft.Opacity = opacity; this.stShadowMarginLeft.Opacity = opacity; } else { this.stShadowSplitOuterRight.Opacity = opacity; this.stShadowSplitInnerRight.Opacity = opacity; this.stShadowMarginRight.Opacity = opacity; } } #endregion #endregion } /// <summary> /// 抛出需要加载的项数据 /// </summary> public class FlipLoadArgs : EventArgs { public readonly List<object> needItems; public readonly bool isNext; public FlipLoadArgs(List<object> _needItems, bool _isNext) { this.needItems = _needItems; this.isNext = _isNext; } } public class FlipEventArgs : EventArgs { public readonly bool isNext; public FlipEventArgs(bool _isNext) { this.isNext = _isNext; } } }
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WinRTXamlToolkit.Controls"> <Style TargetType="local:FlipBookControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:FlipBookControl"> <Grid x:Name="grdContent" Background="{TemplateBinding Background}"> <Grid.RowDefinitions> <RowDefinition Height="30*"/> <RowDefinition Height="750*"/> <RowDefinition Height="30*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="50*"/> <ColumnDefinition Width="600*"/> <ColumnDefinition Width="600*"/> <ColumnDefinition Width="50*"/> </Grid.ColumnDefinitions> <Image x:Name="bookContainer" Stretch="Fill" Canvas.ZIndex="2" Grid.ColumnSpan="4" IsHitTestVisible="False" Grid.RowSpan="3"/> <Border Grid.Row="1" Grid.Column="1" BorderThickness="0" x:Name="C"> <Border.Clip> <RectangleGeometry x:Name="CRect"> </RectangleGeometry> </Border.Clip> <Border.RenderTransform> <CompositeTransform x:Name="transC"></CompositeTransform> </Border.RenderTransform> <ContentPresenter x:Name="CPresenter" Style="{TemplateBinding ItemContainerStyle}" ContentTemplate="{TemplateBinding ItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"></ContentPresenter> </Border> <Border Grid.Row="1" Grid.Column="1" BorderThickness="0" x:Name="D"> <Border.Clip> <RectangleGeometry x:Name="DRect"> </RectangleGeometry> </Border.Clip> <Border.RenderTransform> <CompositeTransform x:Name="transD"></CompositeTransform> </Border.RenderTransform> <ContentPresenter x:Name="DPresenter" Style="{TemplateBinding ItemContainerStyle}" ContentTemplate="{TemplateBinding ItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"></ContentPresenter> </Border> <Border Grid.Row="1" Grid.Column="1" BorderThickness="0" x:Name="E"> <Border.Clip> <RectangleGeometry x:Name="ERect"> </RectangleGeometry> </Border.Clip> <Border.RenderTransform> <CompositeTransform x:Name="transE"/> </Border.RenderTransform> <ContentPresenter x:Name="EPresenter" Style="{TemplateBinding ItemContainerStyle}" ContentTemplate="{TemplateBinding ItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"></ContentPresenter> </Border> <Border Grid.Row="1" Grid.Column="1" BorderThickness="0" x:Name="F"> <Border.Clip> <RectangleGeometry x:Name="FRect"> </RectangleGeometry> </Border.Clip> <Border.RenderTransform> <CompositeTransform x:Name="transF"></CompositeTransform> </Border.RenderTransform> <ContentPresenter x:Name="FPresenter" Style="{TemplateBinding ItemContainerStyle}" ContentTemplate="{TemplateBinding ItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"></ContentPresenter> </Border> <Border Grid.Row="1" Grid.Column="1" BorderThickness="0" x:Name="A"> <Border.Clip> <RectangleGeometry x:Name="ARect"> </RectangleGeometry> </Border.Clip> <Border.RenderTransform> <CompositeTransform x:Name="transA"></CompositeTransform> </Border.RenderTransform> <ContentPresenter x:Name="APresenter" Style="{TemplateBinding ItemContainerStyle}" ContentTemplate="{TemplateBinding ItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"></ContentPresenter> </Border> <Border Grid.Row="1" Grid.Column="1" BorderThickness="0" x:Name="B"> <Border.Clip> <RectangleGeometry x:Name="BRect"> </RectangleGeometry> </Border.Clip> <Border.RenderTransform> <CompositeTransform x:Name="transB"/> </Border.RenderTransform> <ContentPresenter x:Name="BPresenter" Style="{TemplateBinding ItemContainerStyle}" ContentTemplate="{TemplateBinding ItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"></ContentPresenter> </Border> <StackPanel Canvas.ZIndex="3" x:Name="stShadowSplitOuterLeft" Width="43" Opacity="0" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" Margin="-43,0,0,0" RenderTransformOrigin="0.5,0.5"> <StackPanel.RenderTransform> <CompositeTransform x:Name="outerLeftTrans" TranslateX="0"/> </StackPanel.RenderTransform> <StackPanel.Background> <LinearGradientBrush EndPoint="0,0" StartPoint="1,0"> <GradientStop Color="#99000000"/> <GradientStop Color="Transparent" Offset="1"/> </LinearGradientBrush> </StackPanel.Background> </StackPanel> <StackPanel Canvas.ZIndex="3" x:Name="stShadowSplitInnerLeft" Width="51" Opacity="0" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Left" RenderTransformOrigin="0.5,0.5"> <StackPanel.RenderTransform> <CompositeTransform x:Name="innerLeftTrans" TranslateX="0"/> </StackPanel.RenderTransform> <StackPanel.Background> <LinearGradientBrush EndPoint="1,1" StartPoint="0,1"> <GradientStop Color="#99000000"/> <GradientStop Color="#01FFFFFF" Offset="1"/> </LinearGradientBrush> </StackPanel.Background> </StackPanel> <StackPanel Canvas.ZIndex="3" x:Name="stShadowSplitOuterRight" Width="43" Opacity="0" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Right" Margin="0,0,-43,0" RenderTransformOrigin="0.5,0.5"> <StackPanel.RenderTransform> <CompositeTransform x:Name="outerRightTrans" TranslateX="0"/> </StackPanel.RenderTransform> <StackPanel.Background> <LinearGradientBrush EndPoint="1,1" StartPoint="0,1"> <GradientStop Color="#99000000"/> <GradientStop Color="Transparent" Offset="1"/> </LinearGradientBrush> </StackPanel.Background> </StackPanel> <StackPanel Canvas.ZIndex="3" x:Name="stShadowSplitInnerRight" Width="51" Opacity="0" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Right" RenderTransformOrigin="0.5,0.5"> <StackPanel.RenderTransform> <CompositeTransform x:Name="innerRightTrans" TranslateX="0"/> </StackPanel.RenderTransform> <StackPanel.Background> <LinearGradientBrush EndPoint="0,0" StartPoint="1,0"> <GradientStop Color="#99000000"/> <GradientStop Color="#01FFFFFF" Offset="1"/> </LinearGradientBrush> </StackPanel.Background> </StackPanel> <StackPanel x:Name="stShadowMarginLeft" Width="30" HorizontalAlignment="Left" Opacity="0" Grid.Row="1" Grid.Column="1" Canvas.ZIndex="3"> <StackPanel.RenderTransform> <CompositeTransform x:Name="marginLeftTrans" TranslateX="0"/> </StackPanel.RenderTransform> <StackPanel.Background> <LinearGradientBrush EndPoint="1,1" StartPoint="0,1"> <GradientStop Color="#99000000"/> <GradientStop Color="Transparent" Offset="1"/> </LinearGradientBrush> </StackPanel.Background> </StackPanel> <StackPanel x:Name="stShadowMarginRight" Width="30" HorizontalAlignment="Right" Opacity="0" Grid.Row="1" Grid.Column="2" Canvas.ZIndex="3"> <StackPanel.RenderTransform> <CompositeTransform x:Name="marginRightTrans" TranslateX="0"/> </StackPanel.RenderTransform> <StackPanel.Background> <LinearGradientBrush EndPoint="0,0" StartPoint="1,0"> <GradientStop Color="#99000000"/> <GradientStop Color="Transparent" Offset="1"/> </LinearGradientBrush> </StackPanel.Background> </StackPanel> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
Sample: 使用方法
<local:FlipBookControl x:Name="fbc" Speed="10"
ItemTemplate="{StaticResource BookTemplate}">
<local:FlipBookControl.Background>
<ImageBrush ImageSource="ms-appx:///Assets/bookbox-hori.png"/>
</local:FlipBookControl.Background>
<local:FlipBookControl.BookBackgroundBrush>
<ImageBrush ImageSource="ms-appx:///Assets/bg-7.jpg"/>
</local:FlipBookControl.BookBackgroundBrush>
</local:FlipBookControl>
支持ItemsSource 数据源 以及ItemTemplate Binding
DisposeAction 和RestoreItem 2个依赖项 请在使用前填写。用于释放图片流 以及恢复 源
欢迎讨论,分享经验,以及更优的方法。