Silverlight开发技巧总结-实时更新

本文介绍了 Silverlight 开发中的多种技巧,包括 Out-of-Browser 操作、利用独立存储保存用户登录信息、异常处理方法、初始化参数设置及获取、以及 Theme 主题的应用。这些技巧覆盖了从基本操作到高级功能的多个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在silverlight开发涉及编程细节地方较多.因通常章节过小 而又无法单独拿出来逐一讲述. 另外版本更新等问题对同一操作出现差异等,本篇主要目的是把开发遇到问题解决方法和技巧加以总结放在一起. 主要是日常编程设计细节. 简介实用.并不间断实时更新.

(1)Silverlight 4.0 Out of Brower操作:

out of Brower是3.0版本的新特性. 3.0中需要单独配置silverlight Application标识信息. 比较麻烦. 而4.0直接找到项目属性-Silverlight分栏下设置:

启用Run out of Browser. 可以在下面按钮设置 具体配置:

保存. 运行项目即可看见多个提示.

(2)Silverlight利用独立存储用户登录信息:

Silverlight 为客户端,没有了WebForm中服务器端我们常用的会话Session.登录时存储动态用户信息,Cookie可以本地存储,减少开销服务端资源.Silverlight的独立存储恰恰很想WebFrom中Cookie. 因为Application安全考虑. silverlight不允许直接操作本地的文件系统. 但是独立存储机制却提供一个虚拟目录方式访问本地文件系统. 当然silverlight也提供了操作这个虚拟空间的对象和方法. 每个Silverlight Application应用程序都硬盘分配自己独立存储空间. 默认大小为1M.也可根据项目需要修改大小.Isolated Storaged根据应用程序作用域不同分为: 应用程序和站点两种. 使用时分别用IsolatedStorageFile.GetUserStoreForApplication() 和IsolatedStorageFile.GetUserStoreForSite().

 对于用户信息建议使用IsolatedStorageSetting对象独立存储配置以键值对方式存储. 使用如下:

用户登录时存储需要引用空间:

1  // 测试发现普通的Class libiry无法正常引用到SL项目必须用Sl Class libiry
2  using  System.IO.IsolatedStorage;
3  using  System.IO;

存储登录信息: 

 1  // 利用独立存储保存用户登录数据 使用独立存储配置保存key value值
 2  IsolatedStorageSettings userset  = IsolatedStorageSettings.ApplicationSettings;
 3 
 4  // 先清空
 5  userset.Clear();
 6  userset.Add( " username " ,getCurLoginuser.LoginName); // 以键值方式key value
 7  userset.Add( " password " ,getCurLoginuser.LoginPass);
 8 
 9  userset.Add( " uid " , getCurLoginuser.Uid);
10  userset.Save(); // 保存进入

 在需要地方获取: 

1  // 获得当前登录用户信息
2  IsolatedStorageSettings getcuruser  =  IsolatedStorageSettings.ApplicationSettings;
3  this .userInfo.Text  =   " 欢迎: "   +  getcuruser[ " username " ].ToString(); // 通过Setting方法 简单获取
4  this .date.Text  =  DateTime.Now.ToLongDateString();

 如上一种简单方式实现.其实如上方式.虽然能存储用户登录信息. 但有有一个缺点:用户在退出的时候必须主动删除才行,否则会一直保存存储空间中,用户下次访问时 无法访问到页面.

换一种方式我们把用户信息尝试放到Application.Current.Resource中,但又出现一个问题保存后刷新页面程序会重新加载App.原来保存用户信息也就丢失了.这种方式也不可取 类似在Cookie中可以设置Cookie的存储周期以及过期时间. 同理 在IsolatedStorage独立存储中叶可以设置过期时间.

(3)Unhandled Error in Silverlight Application  Code:4004异常处理:

4004这个异常Code编号 在SL2.0甚是常见.版本得到完善后.今天在处理大批量数据时 SL4中又碰到这个4004Code.

异常出现场景:本来一个统计信息表中仅有几十条数据,下午批量增加10W当量数据. 在刚运行程序立马报出4004Code异常 具体信息如下:

Line: 56

Error: Unhandled Error in Silverlight Application 

Code: 4004    

Category: ManagedRuntimeError       

Message: System.InvalidOperationException: Only one WebContextBase can be created per application.

   at System.ServiceModel.DomainServices.Client.ApplicationServices.WebContextBase..ctor(Boolean setAsCurrent)

   at System.ServiceModel.DomainServices.Client.ApplicationServices.WebContextBase..ctor()

   at SlEventManager.WebContext..ctor()

   at SlEventManager.App..ctor()     

除了这写信息 没有任何提示,在SilverLover.com讨论一番.其实碰到这个错误一般在Domain Service DeBug时出现.如果想看到具体程序的详细信息:可以这样方式获取:

A:在silverlight中Server端重写override DomainService 的OnError方法,这样可以在SilverlightClient中TryCatch中获得比较详细的server 错误的信息.快速定位异常.

B:可以用fiddler去监视request/response这样能获得比较详细的错误信息.在浏览器中装一个Web Request跟踪插件. 方式获取 直接看到.

C:方式三就需要Silverlight 与JavaScript进行交互:其实类中OnError属性可以指定一个JavaScript函数来返回Silverlight Application的异常信息. 默认函数名:onSilverlightError,你可以通过Silverlight调用JS函数来显示详细异常信息:

定义JS函数:

ExpandedBlockStart.gif 代码
 1  < script type = " text/JavaScript " >
 2        function  onSilverlightError(sender,args)
 3       {
 4          var  appSource = "" ;
 5          if (sender != null   &&  sender != 0 )
 6         {
 7           appSource = sender.getHost().Source;
 8         }
 9         
10          var  errortype = args.ErrorType;
11          var  errorCode = args.ErrorCode;
12         
13          if (errortype == " ImageError "   ||  errortype == " MediaError " )
14         {
15           return ;
16         }
17         
18          var  errmsg = " Unhandled Error in Silverlight Application  " + appSource + " \n " ;
19         
20         errmsg += " Code: " + errorCode + "  \n " ;
21         errmsg += " Category: " + errortype + " \n " ;
22         errmsg += " Message: " + args.ErrorMessage +   "  \n " ;
23         
24          if (errortype == " ParserError " )
25         {
26          errmsg += " File: " + args.XamlFile + "  \n " ;
27          errmsg += " Line: " + args.lineNumber +   "  \n " ;
28          errmsg += " Position: " + args.charPosition + "  \n " ;
29          
30         }
31          else   if (errortype == " RuntimeError " )
32         {
33          errmsg += " Line: " + args.lineNumber +   "  \n " ;
34          errmsg += " Position: " + args.charPosition + "  \n " ;
35         }
36          throw   new  Error(errmsg);
37       }
38     < / script>

上面代码是从Ruby编译器RedRails中手动写的. 格式上应该能清晰看到一个异常信息组成整个过程.Silverlight中调用Javascript方法如下:

JS在客户端比较的强大.而silverlight提供了两种对JavaScript访问接口:Invoke和InvokeSelf().首先在页面加载事件中把JS写到页面.如下:因为对JS操作徐引用空间:

1  using  System.Windows.Browser;
2 

 加载方法:

ExpandedBlockStart.gif 代码
 1        void  LayoutRoot_Loaded( object  sender, RoutedEventArgs e)
 2          {
 3               // 创建Javascript脚本 简单演示
 4               string  jstxt  =   @" function onSilverlightError(showmsg){alert(showmsg);} " ;
 5              
 6              HtmlElement getelement  =  HtmlPage.Document.CreateElement( " Script " );
 7              getelement.SetAttribute( " type " , " text/javascript " );
 8              getelement.SetProperty( " text " , " jstext " );
 9 
10               // 添加页面中
11              HtmlPage.Document.Body.AppendChild(getelement);
12 
13          }

调用方法:

1  // 调用方法:
2  HtmlPage.Window.Invoke( " onSilverlightError " " 这是Invoke方式调用 " );
3 
4  ScriptObject callclientjs  =  HtmlPage.Window.GetProperty( " onSilverlightError " as  ScriptObject;
5  callclientjs.InvokeSelf( " 这是invokeself方法 " );

如上为两种调用方式:invoke是通过System.Windows类方法调用 而invokeself则是通过一个ScriptObject对象调用.以此在Silverlight中如出现异常可以同JS弹出对话框方式获取具体详细信息. 

(4)Silverlight初始化参数设置和获取.

silverlight承载在页面中包含在一个Div的Object元素中. 关于silverlight插件基本属性. 请参考这里.  不在赘述.

其中有一个initParams属性允许自定义向Silverlight插件初始化参数. 参数在应用程序初始化时传递给Appliaction_StartUp启动事件. 那么在Silverlight中如何设置获取初始化参数.

A:手动设置

ExpandedBlockStart.gif 代码
 1      < div  id ="silverlightControlHost" >
 2           < object  data ="data:application/x-silverlight-2,"  type ="application/x-silverlight-2"  width ="75%"  height ="75%" >
 3             < param  name ="source"  value ="ClientBin/SLClientDemo.xap" />
 4             < param  name ="onError"  value ="onSilverlightError"   />
 5             < param  name ="background"  value ="white"   />
 6             < param  name ="minRuntimeVersion"  value ="4.0.50401.0"   />
 7             < param  name ="autoUpgrade"  value ="true"   />
 8 
 9             <!-- 手动设置传递参数 -->
10             < param  name ="initParams"  value ="Author=chenkai,Date=2010,BlogerTeach=i'm Silverlighter"    />
11 
12             < href ="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50401.0"  style ="text-decoration:none" >
13                  < img  src ="http://go.microsoft.com/fwlink/?LinkId=161376"  alt ="Get Microsoft Silverlight"  style ="border-style:none" />
14             </ a >
15           </ object >< iframe  id ="_sl_historyFrame"  style ="visibility:hidden;height:0px;width:0px;border:0px" >
16           </ iframe >
17           </ div >

注意在initParams属性中设置参数语法:参数采用单一字符串输入格式,其中用逗号 (,) 分隔各个参数,并用等号 (=) 来分隔键与值。例如:"key1=value1,key2=value2,key3=value3"。需要处理分隔符,以便此 API 可以将其作为字典提供.

B:获取参数

silverlight提供两种获取页面传递过来的参数方式:Application_Startup事件中StartupEventArgs.initParams 和在System.Windows.Browser空间下HtmlDocument.QueryString.  在Application_Startup事件中:

ExpandedBlockStart.gif 代码
 1            // 两种方式获取参数
 2              MainPage getpage  =   new  MainPage();
 3               this .RootVisual  = getpage;
 4 
 5              Grid getgrid  =  getpage.LayoutRoots;
 6 
 7               int  count = 0 ;
 8               double  toplenght = 20 ;
 9               foreach  ( string  getkey  in  e.InitParams.Keys)
10              {
11                  count ++ ;
12                   if (count > 0 )
13                  {
14                      toplenght += 20 ;
15                  }
16                  getgrid.Children.Add( new  TextBlock()
17                  {
18                      Text  = string .Format( " 参数{0}值:{1} " , getkey, e.InitParams[getkey]),
19                      Padding = new  Thickness( 15 ,toplenght,toplenght,toplenght),
20                      FlowDirection = FlowDirection.LeftToRight
21                  });
22                   // 获取成功
23              }
24 
25               foreach  ( string  getstrkey  in  HtmlPage.Document.QueryString.Keys)
26              {
27                  count ++ ;
28                   if  (count  >   0 )
29                  {
30                      toplenght  +=   30 ;
31                  }
32 
33                  getgrid.Children.Add( new  TextBlock { 
34                   Text = string .Format( " QueryString参数{0}值{1} " ,getstrkey,HtmlPage.Document.QueryString[getstrkey]),
35                   Padding = new  Thickness( 25 ,toplenght,toplenght,toplenght),
36                   FlowDirection = FlowDirection.LeftToRight
37                  });
38 
39              }

因e.initParams返回值为System.Collections.Generic.IDictionary<String, String>类型. 所以可以直接转键值对类型来获得:

ExpandedBlockStart.gif 代码
1    // 直接转换成字典表
2              IDictionary < string string >  getdic  =  e.InitParams;
3               if  (getdic.Count  >   0 )
4              {
5                  MessageBox.Show(getdic[ " Author " ].ToString() + " 新数据: " + getdic[ " Date " ].ToString());
6              }

两者区别:

initParmams:只要卸载Application_StartUp事件中.当silverlight运行程序后可以通过. StartUpEventArgs或App.Current.Host.InitParams获得, 后者可以在任何Xaml中随时随地获取参数值.

HtmlDocumentPage:可以在Silverlight任何位置调用 直接获取. 但前提是参数值必须存在 更多详细细节请参见MSDN

Silverlight插件作为Aspx页面我们也可以动态修改要传入silverlight初始化参数的值: 修改

1  <!-- 设置参数传递 -->
2             < param  name ="initParams"  value ="Author=chenkai,Date=2010"  runat ="server"  id ="initParams"   />

通过Button事件测试:

1  <!-- 添加一个Button事件测试 -->
2  < asp:Button  ID ="Button1"  runat ="server"  Text ="ChangeParValue"   onclick ="Button1_Click"   />

事件内容:

ExpandedBlockStart.gif 代码
< script  runat ="server" >
    protected 
void  Button1_Click(object sender, EventArgs e)
    {
        
// 修改参数信息
         this .initParams.Attributes.Add( " value " " BookName=chenkaiunion " );
    }
</ script >

当button按钮触发事件页面重新加载App,新设置参数值即在Silverlight程序中生效.测试通过.

(5)Silverlight Theme主题使用:

Silverlight 4相对Silverlight 3 Theme 主题应用上得到增强.Silverlight 4中实现一个Theme步骤.

准备工作: 安装相应版本的SDK. 例如SL4 安装成功后对应路径在:C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Toolkit\Apr10\Themes 下.

实现TwilightBlue 主题:SL 4完整演变成控件:

1       < my:TwilightBlueTheme >
2           < StackPanel  x:Name ="LayoutRoot"  Background ="White"  Orientation ="Vertical"   >
3               < ComboBox  Height ="25"  Margin ="68,76,0,0"  Name ="changestyle"  Width ="230"    />
4               < Button  Content ="Change Silverlight Theme"  Margin ="68,26,0,0"  Height ="32"  Name ="button1"  Width ="231"   />
5           </ StackPanel >
6       </ my:TwilightBlueTheme >

运行后效果:

如果实现多个主题之间切换:

(A)在本地SDK 安装Theme目录下添加相应主题DLL文件引用

(B)再对应的XAML文件添加到项目中

后台通过System.Windows.Controls.Theming空间下静态类ImplicitStyleManager对主题进行动态更新:

1             // 资源字典文件的路径
2              Uri uri  =   new  Uri( " Themes/BubbleCreme.xaml " , UriKind.Relative);
3             ImplicitStyleManager.SetResourceDictionaryUri(LayoutRoot, uri); 
4              // 设置更新模式
5              ImplicitStyleManager.SetApplyMode(LayoutRoot, ImplicitStylesApplyMode.Auto);
6               // 应用样式到StockPanel控件
7              ImplicitStyleManager.Apply(LayoutRoot); 
8 

在说明一下Silverlight 3中与Silverlight 4应用不同之处:

<1> SL 3中不能根据资源中的样式的TargetType将样式自动应用到所有目标类型的元素上, 但SL 4中 则加以完全支持.

<2> SL 3通过将主题应用到容器控件上或将容器控件放在主题控件的内容中的方式,可以将主题自动应用到控件的所有子元素,但无法将主题直接应用到所有页面或用户控件中,例如常用ChildWindows. 而在SL 4中Theme已经支持到ChildWindows应用中.  大大简化自定义子窗体Theme难度.

<3> SL中对空间样式定义效果同主体效果 放在一块时会产生叠加效果. So Theme 没有完全限制住开发者自主生产的能力. 很方便.

转载于:https://www.cnblogs.com/chenkai/archive/2010/05/27/1745522.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值