Silverlight实现超酷翻页效果示例

经常阅读电子杂志的朋友对其流畅自然的翻页过渡效果应当留下了十分深刻的印象。这些杂志都是使用Flash技术制作而成的。总想着能用Silverlight实现这样的效果,去网上查查资料,找到了一个微软官方提供的翻页效果例子。这里再推荐一个外国网站的Silverlight翻页在线实例

 

 

 

效果是十分的赞,只可惜控制的逻辑是用JavaScript代码实现的,这就不利于程序逻辑的整体控制。笔者最近在CodePlex上,找到了一个开源的翻页控件WPF and Silverlight BookControls(点这里进入),用它进行Silverlight翻页效果的开发就显得十分得心应手了。下面就向大家一步一步地介绍Silverlight翻页效果的实现过程。

 

1、建立翻页项目解决方案

点击File->Projects...菜单选项,新建一个ASP.NET Web Application

 

 

 

将新建工程名称命名为FlipPage

 

 

 

在解决方案下继续添加一个Silverlight应用程序项目,将该工程命名为SilverlightClient

 

 

 

在弹出的对话框中,直接点OK按钮。

 

 

 

点击一下“全部保存”按钮,完成项目工程的创建。

 

2、添加必要文件

SilverlightClient项目文件夹下,新建一个名为Dll的文件夹,在里面放入WPF and Silverlight BookControls的动态链接库文件SLMitsuControls.dll(如下图)。在FlipPage项目文件夹下,新建一个名为mediaPictures的子文件夹,在里面放入将在书中显示的图片,如下图所示命名。同样的,在SilverlightClient项目文件夹下,新建一个名为PageType的文件夹,然后再新建两个类分别命名为LeftPage.csRightPage.cs(如下图),它们分别代表了书的偶数和奇数页面,具体代码如下所示(详细的说明请见代码注释)。

 

              

 

LeftPage.cs文件代码:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace SilverlightClient.TypePage 
{
  public class LeftPage : Canvas 
  {
    //定义将在页面上显示的元素
    private Image imgPhoto;
    private Button btnPrevious;
    private Rectangle RecBorder;
    private TextBlock PageNum;
    
    //构造函数
    public LeftPage()
    {
      //页面的设置
      this.Width = 452;
      this.Height = 630;
      this.Background = new SolidColorBrush(Colors.White);
      Canvas.SetLeft(this, 0);
      Canvas.SetTop(this, 0);
      //页面边框的设置
      RecBorder = new Rectangle();
      RecBorder.Width = 452;
      RecBorder.Height = 630;
      Canvas.SetLeft(RecBorder, 0);//设置页面边框在Canvas中的位置,下同。
      Canvas.SetTop(RecBorder, 0);
      RecBorder.Stroke = new SolidColorBrush(Colors.Black);
      RecBorder.StrokeThickness = 0;
      this.Children.Add(RecBorder);
      //照片的设置
      imgPhoto = new Image();
      imgPhoto.Width = 450;
      imgPhoto.Height = 600;
      Canvas.SetLeft(imgPhoto, 1);
      Canvas.SetTop(imgPhoto, 1);
      this.Children.Add(imgPhoto);
      //“前一页”按钮的设置
      btnPrevious = new Button();
      btnPrevious.Width = 150;
      btnPrevious.Height = 20;
      btnPrevious.Content = "<< 前一页";
      btnPrevious.HorizontalContentAlignment = HorizontalAlignment.Center;
      btnPrevious.VerticalContentAlignment = VerticalAlignment.Center;
      btnPrevious.Cursor = Cursors.Hand;
      Canvas.SetLeft(btnPrevious, 151);
      Canvas.SetTop(btnPrevious, 605);
      this.Children.Add(btnPrevious);
      //页码文本的设置
      PageNum = new TextBlock();
      PageNum.Width = 100;
      PageNum.Height = 20;
      PageNum.Text = "00 / 00";
      PageNum.TextAlignment = TextAlignment.Left;
      PageNum.VerticalAlignment = VerticalAlignment.Center;
      PageNum.FontFamily = new FontFamily("Comic sans MS");
      Canvas.SetLeft(PageNum, 10);
      Canvas.SetTop(PageNum, 607);
      this.Children.Add(PageNum);
    }
    //设置图片路径
    public void setterimgPhoto(string path)
    {
      BitmapImage btm = new BitmapImage();
      btm.UriSource = new Uri(path, UriKind.Relative);
      imgPhoto.Source = btm;
    }
    //设置按钮是否可见
    public void setterDisplayBtnPrevious(bool YesNo)
    {
      if (YesNo)
      {
        btnPrevious.Visibility = Visibility.Visible;
      }
      else {
        btnPrevious.Visibility = Visibility.Collapsed;
      }
    }
    //设置页码
    public void setterPageNumber(string currentPageNum, string TotalPageNum) {
        PageNum.Text = currentPageNum + " / " + TotalPageNum;
    }
    //返回按钮单击事件关联
    public Button getbtnPrevious()
    {
      return btnPrevious;
    }

  }
}

 

RightPage.cs文件代码:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace SilverlightClient.TypePage 
{
  public class RightPage : Canvas 
  {
    //定义将在页面上显示的元素
    private Image imgPhoto;
    private Button btnNext;
    private Rectangle RecBorder;
    private TextBlock PageNum;
    
    //构造函数
    public RightPage()
    {
      //页面的设置
      this.Width = 452;
      this.Height = 630;
      this.Background = new SolidColorBrush(Colors.White);
      Canvas.SetLeft(this, 0);//设置页面边框在Canvas中的位置,下同。
      Canvas.SetTop(this, 0);
      //页面边框的设置
      RecBorder = new Rectangle();
      RecBorder.Width = 452;
      RecBorder.Height = 630;
      Canvas.SetLeft(RecBorder, 0);
      Canvas.SetTop(RecBorder, 0);
      RecBorder.Stroke = new SolidColorBrush(Colors.Black);
      RecBorder.StrokeThickness = 0;
      this.Children.Add(RecBorder);
      //照片的设置
      imgPhoto = new Image();
      imgPhoto.Width = 450;
      imgPhoto.Height = 600;
      Canvas.SetLeft(imgPhoto, 1);
      Canvas.SetTop(imgPhoto, 1);
      this.Children.Add(imgPhoto);
      //“后一页”按钮的设置
      btnNext = new Button();
      btnNext.Width = 150;
      btnNext.Height = 20;
      btnNext.Content = "后一页 >>";
      btnNext.HorizontalContentAlignment = HorizontalAlignment.Center;
      btnNext.VerticalContentAlignment = VerticalAlignment.Center;
      btnNext.Cursor = Cursors.Hand;
      Canvas.SetLeft(btnNext, 151);
      Canvas.SetTop(btnNext, 605);
      this.Children.Add(btnNext);
      //页码文本的设置
      PageNum = new TextBlock();
      PageNum.Width = 100;
      PageNum.Height = 20;
      PageNum.Text = "00 / 00";
      PageNum.TextAlignment = TextAlignment.Right;
      PageNum.VerticalAlignment = VerticalAlignment.Center;
      PageNum.FontFamily = new FontFamily("Comic sans MS");
      Canvas.SetLeft(PageNum, 340);
      Canvas.SetTop(PageNum, 607);
      this.Children.Add(PageNum);
    }
    //设置图片路径
    public void setterimgPhoto(string path)
    {
        BitmapImage btm = new BitmapImage();
        btm.UriSource = new Uri(path, UriKind.Relative);
        imgPhoto.Source = btm;
    }
    //设置按钮是否可见
    public void setterDisplayBtnNext(bool YesNo)
    {
        if (YesNo)
        {
            btnNext.Visibility = Visibility.Visible;
        }
        else
        {
            btnNext.Visibility = Visibility.Collapsed;
        }
    }
    //设置页码
    public void setterPageNumber(string currentPageNum, string TotalPageNum)
    {
        PageNum.Text = currentPageNum + " / " + TotalPageNum;
    }
    //返回按钮单击事件关联
    public Button getbtnNext()
    {
        return btnNext;
    }

  }
}
 

3、构建应用程序界面

详细的说明请见代码注释。

MainPage.xaml文件代码:

<UserControl x:Class="SilverlightClient.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SLMitsuControls;assembly=SLMitsuControls"         
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480" Loaded="UserControl_Loaded">
  <Grid x:Name="LayoutRoot">
      <Canvas x:Name="layout" Background="White" Width="906" Height="630" Canvas.Left="0" Canvas.Top="0">
        <!--显示层-->  
        <Canvas x:Name="canvasBook" Background="White" Width="906" Height="630" Canvas.Left="0" Canvas.Top="0" Visibility="Collapsed">
            <local:UCBook x:Name="book" Width="906" Height="630" Canvas.Left="0" Canvas.Top="0" /><!--BookControl-->
        </Canvas>
        <!--加载层-->
        <Canvas x:Name="canvChanging" Width="500" Height="75" Canvas.Left="200" Canvas.Top="250" Visibility="Collapsed" Background="Transparent">
            <TextBlock x:Name="changingText" Text="页面加载中" Width="200" Height="30" Canvas.Left="0" Canvas.Top="0" FontFamily="comic sans ms" FontSize="14"></TextBlock>
            <ProgressBar x:Name="changingProgressBar" Width="500" Height="30" Canvas.Left="0" Canvas.Top="30"></ProgressBar>
        </Canvas>
      </Canvas>
  </Grid>
</UserControl>

 

4、设置应用程序控制逻辑

 

详细的说明请见代码注释。

1MainPage.xaml.cs文件代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
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.Shapes;
using System.Threading;
using SLMitsuControls;

namespace SilverlightClient
{
    public partial class MainPage : UserControl, IDataProvider
    {
        //定义全局变量
        private List<object> PageObjectList;//页面对象列表
        public enum PageType { right, left };//页面类型
        public string fileMedia = "";//文件媒体
        public string headerPage = "";//首页
        public int maxiPageNum = 0;//最大页数
        public enum Location { local, web };//枚举应用程序所在
        public Location modeLocation;
        private int pageDownload = 0;//下载的页面数
        private string uriResources = "";//Uri地址

        //构造函数
        public MainPage()
        {
            InitializeComponent();
            PageObjectList = new List<object>();
        }

        //UserControl事件触发处理
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (modeLocation == Location.local)
            {
                this.canvChanging.Visibility = Visibility.Collapsed;
                this.canvasBook.Visibility = Visibility.Visible;
                //填充页面列表
                FillPagesList();
            }
            if (modeLocation == Location.web)
            {
                this.canvChanging.Visibility = Visibility.Visible;
                this.canvasBook.Visibility = Visibility.Collapsed;
                //开始下载页面
                DownloadPages();
            }
        }

        //开始将页面填充至List中
        private void FillPagesList()
        {
            //用页面填充列表
            for (int xx = 1; xx <= maxiPageNum; xx++)
            {
                if (xx % 2 != 0)
                {
                    //前一页即奇数页
                    AddPageToList(PageType.right, fileMedia + "/" + headerPage + xx.ToString("00") + ".jpg", xx.ToString(),
                      maxiPageNum.ToString(), true);
                }
                else
                {
                    //后一页即偶数页
                    AddPageToList(PageType.left, fileMedia + "/" + headerPage + xx.ToString("00") + ".jpg", xx.ToString(),
                      maxiPageNum.ToString(), true);
                }
            }

            //移除最后一页的按钮
            TypePage.RightPage page = PageObjectList[maxiPageNum - 1] as TypePage.RightPage;
            page.setterDisplayBtnNext(false);

            //为翻页按钮指派事件触发处理
            for (int xx = 1; xx < maxiPageNum; xx++)
            {
                if (xx % 2 != 0)
                {
                    //前一页即奇数页
                    TypePage.RightPage pp = PageObjectList[xx - 1] as TypePage.RightPage;
                    Button btnNext = pp.getbtnNext();
                    btnNext.Click += new RoutedEventHandler(btnNext_Click);
                }
                else
                {
                    //后一页即偶数页
                    TypePage.LeftPage pp = PageObjectList[xx - 1] as TypePage.LeftPage;
                    Button btnPrevious = pp.getbtnPrevious();
                    btnPrevious.Click += new RoutedEventHandler(btnPrevious_Click);
                }
            }

            //为Book设置数据内容
            book.SetData(this);
        }

        //向页面列表中添加具体页面
        private void AddPageToList(PageType pageType, string pathImage, string numPage, string numMaxiPage,
          bool showBtnYesNo)
        {
            switch (pageType)
            {
                case PageType.right:
                    TypePage.RightPage pcd = new SilverlightClient.TypePage.RightPage();
                    pcd.setterimgPhoto(pathImage);
                    pcd.setterPageNumber(numPage, numMaxiPage);
                    pcd.setterDisplayBtnNext(showBtnYesNo);
                    PageObjectList.Add(pcd);
                    break;
                case PageType.left:
                    TypePage.LeftPage pcg = new SilverlightClient.TypePage.LeftPage();
                    pcg.setterimgPhoto(pathImage);
                    pcg.setterPageNumber(numPage, numMaxiPage);
                    pcg.setterDisplayBtnPrevious(showBtnYesNo);
                    PageObjectList.Add(pcg);
                    break;
            }
        }

        //“下一页”按钮事件触发处理
        private void btnNext_Click(object sender, RoutedEventArgs e)
        {
            book.AnimateToNextPage(500);
        }

        //“上一页”按钮事件触发处理
        private void btnPrevious_Click(object sender, RoutedEventArgs e)
        {
            book.AnimateToPreviousPage(500);
        }

        //从网络上下载页面
        private void DownloadPages()
        {
            this.canvChanging.Visibility = Visibility.Visible;
            this.uriResources = Application.Current.Host.Source.AbsoluteUri;
            int index = uriResources.IndexOf("SilverlightClient.xap");
            uriResources = uriResources.Substring(0, index);
            this.changingProgressBar.Minimum = 0;
            this.changingProgressBar.Maximum = maxiPageNum - 1;
            string theResources = uriResources + fileMedia + "/" + headerPage + (pageDownload + 1).ToString("00") + ".jpg";
            string theResourcesNum = headerPage + (pageDownload + 1).ToString("00") + ".jpg";
            AsynchronouslyDownloadPage(theResources, theResourcesNum);
        }

        //异步下载页面
        private void AsynchronouslyDownloadPage(string path, string num)
        {
            WebClient unWeb = new WebClient();
            unWeb.DownloadStringCompleted += new DownloadStringCompletedEventHandler(unWeb_DownloadStringCompleted);
            unWeb.DownloadStringAsync(new Uri(path));
            this.changingText.Text = "正在下载 : " + num;
            this.changingProgressBar.Value = this.pageDownload;
        }

        //异步下载页面完成事件触发处理
        private void unWeb_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            this.pageDownload++;
            if (this.pageDownload < this.maxiPageNum)//持续不断下载页面直到所有页面都下完
            {
                string theResources = uriResources + fileMedia + "/" + headerPage + (pageDownload + 1).ToString("00") + ".jpg";
                string theResourcesNum = headerPage + (pageDownload + 1).ToString("00") + ".jpg";
                AsynchronouslyDownloadPage(theResources, theResourcesNum);
            }
            else
            {
                FillPagesList();
                this.canvChanging.Visibility = Visibility.Collapsed;
                this.canvasBook.Visibility = Visibility.Visible;
            }
        }

        //强制声明接口
        #region IDataProvider Members
        public object GetItem(int index)
        {
            return PageObjectList[index];
        }
        public int GetCount()
        {
            return PageObjectList.Count;
        }
        #endregion

    }
}

 

2App.xaml.cs文件代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightClient
{
    public partial class App : Application
    {
        public string gFileMedia = "";
        public string gHeaderPage = "";
        public int gPageNumber = 0;
        public string gModeLocation = "";
        
        public App()
        {
            this.Startup += this.Application_Startup;
            this.Exit += this.Application_Exit;
            this.UnhandledException += this.Application_UnhandledException;

            InitializeComponent();
        }

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            int paramOk = 0;
            //从HTML中取出初始化数据
            if (e.InitParams.ContainsKey("gFile"))
            {
                gFileMedia = e.InitParams["gFile"];
                paramOk++;
            }
            if (e.InitParams.ContainsKey("gHeaderPage"))
            {
                gHeaderPage = e.InitParams["gHeaderPage"];
                paramOk++;
            }
            if (e.InitParams.ContainsKey("gNum"))
            {
                string recup = e.InitParams["gNum"];
                gPageNumber = int.Parse(recup);
                paramOk++;
            }
            if (e.InitParams.ContainsKey("gLocation"))
            {
                gModeLocation = e.InitParams["gLocation"];
                paramOk++;
            }
            if (paramOk == 4)
            {
                //初始化MainPage
                MainPage maPage = new MainPage();
                maPage.fileMedia = gFileMedia;
                maPage.headerPage = gHeaderPage;
                maPage.maxiPageNum = gPageNumber;
                if (gModeLocation.CompareTo("local") == 0)
                {
                    maPage.modeLocation = MainPage.Location.local;
                }
                if (gModeLocation.CompareTo("web") == 0)
                {
                    maPage.modeLocation = MainPage.Location.web;
                }
                this.RootVisual = maPage;
            }
        }

        private void Application_Exit(object sender, EventArgs e)
        {
            
        }

        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (!System.Diagnostics.Debugger.IsAttached)
            {
                e.Handled = true;
                Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
            }
        }
        private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
        {
            try
            {
                string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
                errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");

                System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
            }
            catch (Exception)
            {
            }
        }
    }
}

 

3SilverlightClientTestPage.aspx文件(位于工程FlipPage文件夹下)中,添加用绿色粗体标明的代码:

<body>
    <form id="form1" runat="server" style="height:100%">
    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
          <param name="source" value="ClientBin/SilverlightClient.xap"/>
          <param name="onError" value="onSilverlightError" />
          <param name="background" value="white" />
          <param name="minRuntimeVersion" value="3.0.40624.0" />
          <param name="autoUpgrade" value="true" />
          <!--设置Book初始化参数-->
          <param name="initParams" value="gFile=mediaPictures, gHeaderPage=albumPictures, gNum=9, gLocation=web" />
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
              <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
          </a>
        </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
    </form>
</body>

5、最终效果图