• Jeff   2014/8/14 12:42:00
  • Silverlight中如何显示用户自定义的 Splash Screen (初始屏幕)
  • 关键字: Silverlight 自定义 初始屏
  •   一、什么是Splash Screen 
    Splash Screen就是Silverlight的初始屏幕,也即我们经常在Silverlight应用中看到的如下图的屏幕界面:
                                              
     
    当我们运行某个Silverlight应用程序时,这个Silverlight应用程序的界面便会展示给我们。但在它的程序界面展示给我们之前,Silverlight所必须完成的工作就是:在客户端把清单中引用的程序集下载(包括需要预先加裁的有些资源),并把它们加载到Silverlight应用程序的AppDomain中。如果这个工作没有做完,我们是看不到Silverlight应用程序的界面的。

    如果这个过程很短,用户将不会遇到明显的加载时间滞后的情况。但是,如果需要下载的数据包特别大,那么用户就要等待较长的时间。而在这个空档,Silverlight提供了"初始屏幕"来暂时安慰一下焦急的用户。就像我们以前在看电影前的“加演”一样,在电影正式播放前,给观众播放一些广告或宣传资料。

    二、Splash Screen使用情景
     Splash Screen常用在下面几个地方:

     1、显示下载进度 
     2、显示动画,即使不必使用它们来显示下载进度 
     3、提供品牌,这可以包括文本、向量图形甚至视频 
     4、显示产品信息,例如免责声明 
     

    当然,你还可以拓展出它的其它用法来.


    三 、Splash Screen的相关进度和相关事件 
    Silverlight 初始屏幕模型依赖于 Silverlight 插件公开的三个属性:

     1、splashscreensource:下载主数据包 (source) 的过程中显示的 XAML 页面的 URI。 
     2、onsourcedownloadprogresschanged:引用一个 JavaScript 事件处理程序,在下载 source 的过程中,将会持续调用该处理程序。 
     3、onsourcedownloadcomplete:引用一个 JavaScript 事件处理程序,source 下载完成后,将会调用一次该处理程序 
       
    四、下面我们来一步一步地演示如何添加用户自定义初始屏幕(Splash Screen) 

    我们所定义的Splash屏幕就是一个进度条,当我们启动Silverlight应用程序时,我们首先看到的就是这个进度条,这个进度条展示了Silverlight当前客户端下载所需程序集以及相关资源的完成情况,当然,我们也可以设计出其它动画或宣传资料以代替此处的下载进度条。

    当进度条执行到100%时,我们就进入了Silverlight应用程序的应用界面,此处就是一个简单的Silverlight按钮控件。

    下面,我们来进入我们的具体操作:
    (一)、设置项目文件 
    1、打开 Visual Studio 2008。从应用程序的 Silverlight 项目开始。添加新的Silverligth应用程序,将程序命名为: SLSplashScreen。
    2、请自己找一个比较大的文件(在本例中,我找了一个名为"疯狂的企鹅.wmv"的文件,它的大小为40M),当然,文件类型不限。这个文件复制到Silverlight项目目录中,然后将其作为现有项添加到此项目中。如图:
                      
    3、选中"疯狂的企鹅.wmv"文件,点击鼠标右键,跳出右键菜单,选"属性",把这个文件的"生成操作"项设置为“嵌入的资源”或“资源”。如图:
                     
    这样作的目的是:为了引入足够长的下载时间以使初始屏幕可检测到,所以特意使数据包大一些。要实现该目的,最快捷的方法是将大型嵌入式资源文件(即使实际上并不引用这些文件,它们也会增加数据包的大小)与主程序集打包在一起。通过上述操作,我们便把"疯狂的企鹅.wmv"这个近40M大小的文件引入到程序集和数据包中
    4、设计Silverlight应用程序界面。
    打开Page.xaml文件,在这里,我们只添加一个按钮控件。代码如下:   

     <UserControl x:Class="SLSplashScreen.Page"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        Width="400" Height="300">
        <Grid x:Name="LayoutRoot" Background="White">
            <Button Width="200" Height="80" Content="Splash 完成,显示本按钮"></Button>
        </Grid>
    </UserControl>

    (二)、添加自定义初始屏幕(Splash Screen) 
    1、在解决方案资源管理器中右击 SLSplashScreen.Web,选择“属性”。单击“Web”选项卡。将“启动操作”的默认页从 SLSplashScreenTestPage.aspx改为 SLSplashScreenTestPage.html。 
     如图:

    2、在解决方案资源管理器中右击 SLSplashScreen.Web,选择“添加”、“新建项”。在“类别”树视图中选择“Silverlight”选项。选择“Silverlight JScript 页”[Silverlight JScript Page]选项。将页面命名为 MySplashScreen.xaml。单击“添加”。 
    如图:

    如果 MySplashScreen.xaml尚未打开,请打开它进行编辑。您将要在其中创作初始屏幕。“全选”,“粘贴”下面的代码以覆盖现有代码,然后保存文件(在此外,我们是创建了一个下载进度条)。

    当然,你可以用Expression Blend进行配合编辑和修改,以达到自己的要求。

    下面就是MySplashScreen.xaml内容:

    <Canvas
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            x:Name="parentCanvas"
            Width="1024"
            Height="768"
            >
      <Canvas.Background>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
          <GradientStop Color="#FF0E3BAE" Offset="0"/>
          <GradientStop Color="#FFB2C4F2" Offset="0.406"/>
          <GradientStop Color="#FF567EE3" Offset="0.982"/>
        </LinearGradientBrush>
      </Canvas.Background>
      <Canvas Canvas.Top="228.834" Canvas.Left="246.329" Width="357" Height="31.379">
        <Rectangle Width="27.545" Height="1" x:Name="uxProgress" Canvas.Top="29.545" Canvas.Left="1.4" RadiusX="0" StrokeThickness="6" RadiusY="0">
          <Rectangle.RenderTransform>
            <TransformGroup>
              <ScaleTransform x:Name="uxProgressBar" ScaleX="1" ScaleY="0"/>
              <SkewTransform AngleX="0" AngleY="0"/>
              <RotateTransform Angle="270"/>
              <TranslateTransform X="0" Y="0"/>
            </TransformGroup>
          </Rectangle.RenderTransform>
          <Rectangle.Fill>
            <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
              <GradientStop Color="#FFFFFFFF" Offset="1"/>
              <GradientStop Color="#FFFFFFFF" Offset="0"/>
              <GradientStop Color="#FF34D029" Offset="0.28"/>
              <GradientStop Color="#FF53D029" Offset="0.72"/>
            </LinearGradientBrush>
          </Rectangle.Fill>
        </Rectangle>

    <TextBlock x:Name="uxStatus" Height="25" Canvas.Left="125" Text="正在加载中..........." TextWrapping="Wrap" Canvas.Top="4.16" Foreground="#FFEE326A"/>

        <Path Width="356.85" Height="1" Fill="#FF3A3A3A" Stretch="Fill" Stroke="#FF000000" Canvas.Top="0" Data="M0,170.5 L356.84209,170.5" Opacity="0.35" StrokeThickness="1"/>
        <Path Width="1.662" Height="29.03" Fill="#FF3A3A3A" Stretch="Fill" Stroke="#FF000000" Canvas.Top="0.48" Canvas.Left="0.2" Data="M360,168 L360,0" Opacity="0.35" />

        <Path Width="357.84" Height="1" Fill="#FF3A3A3A" Stretch="Fill" Stroke="#FF000000" Canvas.Top="29" Data="M0,170.5 L356.84209,170.5" Opacity="0.35"/>
        <Path Width="358.85" Height="1" Fill="#FFA2A2A2" Stretch="Fill" Stroke="#FF000000" Canvas.Top="30" Data="M0,170.5 L356.84209,170.5" Opacity="0.25"/>
        <Path Width="1.662" Height="30" Fill="#FF3A3A3A" Stretch="Fill" Stroke="#FF000000" Canvas.Left="356.01" Data="M360,168 L360,0" Opacity="0.35" Canvas.Top="-0.498"/>
        <Path Width="1" Height="31" Fill="#FFA2A2A2" Stretch="Fill" Stroke="#FF000000" Canvas.Left="357.333" Data="M360,168 L360,0" Opacity="0.245" Canvas.Top="-0.498" />
      </Canvas>
    </Canvas>


    4、打开SLSplashScreenTestPage.html进行编辑。
    找到如下代码:

    <object data="data:application/x-silverlight-2,"  type="application/x-silverlight-2" width="100%" height="100%">
                <param name="source" value="ClientBin/SLSplashScreen.xap"/>
                <param name="onerror" value="onSilverlightError" />
                <param name="background" value="white" />
                <param name="minRuntimeVersion" value="2.0.31005.0" />
                <param name="autoUpgrade" value="true" />
                <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
                     <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="获取 Microsoft Silverlight" style="border-style: none"/>
                </a>
        </object>

            这是实例化 Silverlight 插件的对象标记。
           在此,我们找到标记

    <param name="source" value="ClientBin/SLSplashScreen.xap"/> 从路径中移除 ClientBin/。现在,修改后的标记应为<param name="source" value="SLSplashScreen.xap"/>保存该文件,并使其保持打开状态。 
         
    5、在解决方案资源管理器中,将文件 SLSplashScreen.xap拖出 ClientBin/ 目录,放置到 SLSplashScreen.Web的根下,如图:
         
                

    6、返回到SLSplashScreenTestPage.html的 Silverlight object 元素区域进行编辑。请注意,当前已存在大量作为 object 的子元素的“params”元素。现在将要添加几个 params 元素以添加您的自定义初始屏幕信息。添加以下 params 元素:      

                <!-- 下面是我们添加的内容-->
               <param name="splashscreensource" value="MySplashScreen.xaml"/>
               <param name="onSourceDownloadProgressChanged" value="onSourceDownloadProgressChanged" />    
               <param name="onsourcedownloadcomplete" value="onsourcedownloadcomplete" />    
    7、第二、三个 params 元素引用 JavaScript 事件处理程序,您必须现在定义该处理程序。在解决方案资源管理器中右击SLSplashScreen.Web。在解决方案的文件列表中找到文件 MySplashScreen.js(该文件是在上一步添加 SplashScreen.xaml 时添加的)。打开MySplashScreen.js进行如下编辑:
     i、删除 SplashScreen.js 中所有之前存在的内容。
     ii、在其中粘贴下面的 onSourceDownloadProgressChanged与onsourcedownloadcomplete 函数,该函数将会更新 MySplashScreen.xaml 中的进度栏,显示完成状态。   

    function onSourceDownloadProgressChanged(sender, eventArgs) {
         sender.findName("uxStatus").Text = "Loading: " + Math.round((eventArgs.progress * 1000)) / 10 + "%";
         sender.findName("uxProgressBar").ScaleY = eventArgs.progress * 356;
     }
     
    function onsourcedownloadcomplete(sender, eventArgs) {
         sender.findName("uxStatus").Text= "已经完成!";
         alert("已经完成!");
     } 
     
      
    8、 返回到SLSplashScreenTestPage.html进行编辑。您仍旧需要引用刚刚创建的 JavaScript 文件。在紧挨 HTML 中 head 元素的后面,添加以下内容:

    <script type="text/javascript" src="MySplashScreen.js"></script>

    SLSplashScreenTestPage.html全部代码如下:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <!-- 保存自 URL=(0014)关于:Internet -->
    <head>
        <title>SLSplashScreen</title>

        <style type="text/css">
        html, body {
            height: 100%;
            overflow: auto;
        }
        body {
            padding: 0;
            margin: 0;
        }
        #silverlightControlHost {
            height: 100%;
        }
        </style>
        <script type="text/javascript" src="Silverlight.js"></script>
        <script type="text/javascript">
            function onSilverlightError(sender, args) {
            
                var appSource = "";
                if (sender != null && sender != 0) {
                    appSource = sender.getHost().Source;
                } 
                var errorType = args.ErrorType;
                var iErrorCode = args.ErrorCode;
                
                var errMsg = "Silverlight 2 应用程序中未处理的错误 " +  appSource + "\n" ;

                errMsg += "代码: "+ iErrorCode + "    \n";
                errMsg += "类别: " + errorType + "       \n";
                errMsg += "消息: " + args.ErrorMessage + "     \n";

                if (errorType == "ParserError")
                {
                    errMsg += "文件: " + args.xamlFile + "     \n";
                    errMsg += "行号: " + args.lineNumber + "     \n";
                    errMsg += "位置: " + args.charPosition + "     \n";
                }
                else if (errorType == "RuntimeError")
                {           
                    if (args.lineNumber != 0)
                    {
                        errMsg += "行号: " + args.lineNumber + "     \n";
                        errMsg += "位置: " +  args.charPosition + "     \n";
                    }
                    errMsg += "方法名称: " + args.methodName + "     \n";
                }

                throw new Error(errMsg);
            }
        </script>
    </head>

    <script type="text/javascript" src="MySplashScreen.js"></script>

    <body>
        <!-- 此处显示 Silverlight 的运行时错误。
        它将包含调试信息并且调试完成时应删除或隐藏此信息 -->
        <div id='errorLocation' style="font-size: small;color: Gray;"></div>

        <div id="silverlightControlHost">
            <object data="data:application/x-silverlight-2,"  type="application/x-silverlight-2" width="100%" height="100%">
                <param name="source" value="SLSplashScreen.xap"/>
                <param name="onerror" value="onSilverlightError" />
                <param name="background" value="white" />
                <param name="minRuntimeVersion" value="2.0.31005.0" />
                <param name="autoUpgrade" value="true" />
                <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">
                     <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="获取 Microsoft Silverlight" style="border-style: none"/>
                </a>
                <!-- 下面是我们添加的内容-->
               <param name="splashscreensource" value="MySplashScreen.xaml"/>
               <param name="onSourceDownloadProgressChanged" value="onSourceDownloadProgressChanged" />    
               <param name="onsourcedownloadcomplete" value="onsourcedownloadcomplete" />            
               
                   
            </object>
            <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>
        </div>
    </body>
    </html>
    最后,生成项目并确保它编译。
    此时启动操作现在将加载 SLSplashScreenTestPage.html,并首先加载初始屏幕,然后加载源,效果如图: