WCF RIA 服务 (三十五)-- 身份验证、角色、个性化 6

演练:在Silverlight Business应用程序中使用身份验证服务
Silverlight Business应用程序模板创建的解决方案自动允许身份验证(验证模式为Forms),角色和个性化功能。解决方案包含了数据表格来登录已经存在的用户和注册新用户。我们不用写额外的代码就可以使用这些特性。我们也可以通过定义角色、个性化属性来自定义解决方案。

在本演练中,我们将学习如何在Silverlight Business应用程序中使用身份验证、角色和个性化功能。我们将根据用户的凭证来限制对某些域操作的访问,并根据用户的偏好来定制用户界面。我们将使用ASP.NET网站管理工具来管理角色和用户。

 

创建网站、用户、角色
我们可以使用 Silverlight Business应用程序模板提供的特性,来快速实施验证功能。在下面的章节,我们使用ASP.NET配置工具来创建用户和角色,并登陆此用户。我们还通过Silverlight Business应用程序提供的注册表格来注册新用户。

   1.  在Visual Studio中,选择"文件->新建->项目"."新建项目"对话框打开。
   2.  选择Silverlight项目类型。
   3.  选择Silverlight Business Application模板,并命名为ExampleBusinessApplication.
   
   4.  点击"OK".注意创建的项目结构。这个SL客户端项目中在Views文件夹中包含了SL页面。这些页面允许登陆用户和注册新用户。
   5.  打开ASP.NET 网站管理工具。(首先,在资源管理器中,选择服务端项目,然后打开ASP.NET配置工具。
   6.  在项目菜单中,选择ASP.NET Configuration.如果在项目菜单中,看不到ASP.NET Configuration选项,有可能是选择了客户端项目。
  
   7. 在ASP.NET网站管理工具中选择"安全"标签。
  
   8.  在"角色"的部分,点击"创建或管理角色"链接。
   9.  添加一个名为Managers的角色,并点击"添加角色"按钮。
  
   10.  在右下角,点击"返回"按钮。
   11.  在“用户"的部分,点击"创建用户"按钮。
   12.  使用下面的值来创建新用户,并选择Managers角色复选框。
    - User Name : CustomerManager
    - Password : P@ssword
    - E-mail : someone@example.com
    - Security Question : Favorite color?
    - Security Answer : Blue
    - Managers role : selected
   13.  点击"创建用户"按钮。
   14.  关闭ASP.NET网站管理工具。
   15.  运行解决方案。应用程序的首页将会显示在web浏览器中。
   16.  在页面的右上角,点击”登陆"链接。登陆窗口将会出现。
   17.  为用户名称输入CustomerManager,为密码输入p@ssword,并点击"OK"按钮。
  
   现在我们就登陆这个用户了,注意到在页面右上角出现文本"Welcome CustomerManager"。
   18.  点击"登出"按钮。这时我们就不再以CustomerManager登陆了。
   下面的步骤,我们通过注册表格创建一个新用户。
   19.  再次点击"登陆"链接。
   20.  在登陆对话框中,点击"现在就注册"链接。注册表格就会出现了。
   21.  用下面的信息填充注册表。
        Username: SalesUser

        Friendly name: SalesUser

        Email: someone@example.com

        Password: P@ssword

        Security Question: What was the color of your first car?

        Security Answer: Green
    
   22.  点击"OK",创建一个新用户。注意,我们现在已经作为SalesUser登陆了。
   23.  关闭浏览器。
   24.  打开ASP.NET网站管理工具,点击"安全"标签。注意到已经有了两个用户和角色,即使我们只创建了一个角色。
   25.  点击“创建或管理角色”,注意到Managers和Registered Users角色。Registered User角色是Business应用程序模板自动生成的。
  
   26.  对"Registered Users",点击"管理"链接。注意,通过应用程序添加的名为SalesUser的用户已经在Registered Users角色中了。
   27.  关闭ASP.NET网站管理工具。

 

定义访问权限和个性化属性

我们通过为域服务应用 RequiresAuthenticationAttribute和RequiresRoleAttribute属性,来限制对域服务的访问。如果域操作没有属性,对所有用户有效。在域操作上添加属性,并不能阻止用户调用域操作。只是没有所需凭证的用户会收到一个异常。

 

根据角色限制显示数据
   1.  在资源管理器中,在服务端项目中,点击App_Data文件夹,选择"添加->已存在项"。
   2.  在"添加已存在项"对话框中,添加AdventureWorksLT示例数据库。
   3.  在服务端,添加一个新项,并选择ADO.NET Entity Data Model模板。
   4.  命名模型为AdventureWorksModel.edmx,并点击"添加"."实体数据模型向导"将会出现。
   5.  选择"从数据库生成"选项,并点击"下一步".
   6.  选择AdventureWorksLT数据库,并点击"下一步"。
   7.  从数据库对象列表中,选择Customer,Product,以及SalesOrderHeader表,然后点击"完成"。实体数据模型将会出现在设计器中。
   8.  生成解决方案。
   9.  在服务端,添加一个新项,并选择Domain Service Class模板。
   10.  命名为AdventureWorksDomainService,然后点击"添加"。
   11.  在"添加新域服务类"对话框中,选择Customer,Product和SalesOrderHeader实体。
  
   12.  点击"OK"以完成创建域服务。
   13.  在AdventureWorksDomainService类中,对GetSalesOrderHeader方法添加 RequiresAuthenticationAttribute属性。

1  [RequiresAuthentication()]   
2  public  IQueryable < salesorderheader >  GetSalesOrderHeaders()   
3  {   
4       return   this .ObjectContext.SalesOrderHeaders;   
5 

 

   14.  对GetCustomers方法添加RequiresRoleAttribute属性,并设置所需的角色为"Managers"。

1  [RequiresRole( " Managers " )]   
2  public  IQueryable < customer >  GetCustomers()   
3  {   
4       return   this .ObjectContext.Customers;   
5  }

 

GetProducts 方法对所有用户都可用,GetSalesOrderHeader只对验证用户可用,GetCustomers方法只对属于Managers角色的用户可用。

ExpandedBlockStart.gif 代码
 1  [EnableClientAccess()]   
 2  public   class  AdventureWorksDomainService : LinqToEntitiesDomainService < adventureworkslt_dataentities >    
 3  {   
 4      [RequiresRole( " Managers " )]   
 5       public  IQueryable < customer >  GetCustomers()   
 6      {   
 7           return   this .ObjectContext.Customers;   
 8      }   
 9       public  IQueryable < product >  GetProducts()   
10      {   
11           return   this .ObjectContext.Products;   
12      }   
13      [RequiresAuthentication()]   
14       public  IQueryable < salesorderheader >  GetSalesOrderHeaders()   
15      {   
16           return   this .ObjectContext.SalesOrderHeaders;   
17      }   
18  }

 

 

下面我们在Web.config文件中定义个性法属性。当我们把属性添加到服务端的用户类时,将会为客户端项目生成对应的属性。

   1.  在服务端项目,打开Web.config文件。
   2.  在元素内,添加名为DefaultRows的个性化属性。这个属性将保持用户对显示的数据数量的偏爱。

1  < profile >   
2     < properties >   
3       < add  name ="FriendlyName" ></ add >   
4       < add  type ="System.Int32"  defaultvalue ="10"  name ="DefaultRows" ></ add >   
5     </ properties >
6  </ profile >

 

   3.  保存Web.config文件。
   4.  在服务端项目中,展开Models文件夹。
   5.  打开User.cs或User.vb文件,添加名为DefaultRows属性。

ExpandedBlockStart.gif 代码
 1  namespace  ExampleBusinessApplication.Web   
 2  {   
 3       using  System.Runtime.Serialization;   
 4       using  System.Web.Ria.ApplicationServices;   
 5       public   partial   class  User : UserBase   
 6      {   
 7          [DataMember]   
 8           public   string  FriendlyName {  get set ; }   
 9           public   int  DefaultRows {  get set ; }   
10      }   
11  }

 

 

从客户端使用身份验证服务
在调用有限制权限的域操作时,我们应该对用户检查所需的凭证。否则,将会抛出一个异常。在下面的部分,我们将检查用户的凭证,并根据用户的凭证来填充一个到三个DataGrid控件。我们会根据用户个性化中的属性来得到显示的记录数量。对没有验证的用户,默认的值是10。这部分没有让用户更改DefaultRows个性化属性的方式,不过在以后的部分会添加这个方式。

 

添加一个 Silverlight页面来显示数据
   1.  在客户端,在Views文件夹中添加新项。
   2.  选择Silverlight Page模板,并命名为Reports.xaml。
   3.  打开MainPage.xaml文件,并名为Link2的超链接按钮下面添加一个指向Reports页面的链接。

ExpandedBlockStart.gif 代码
1  < rectangle  x:name ="Divider2"  style ="" >   
2       < hyperlinkbutton  x:name ="Link3"  style =""  NavigateUri ="/Reports"  TargetName ="ContentFrame"  Content =" {Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}} " />   
3       </ hyperlinkbutton >
4  </ rectangle >

 

   4.  在Assets\Resources文件夹内,打开ApplicationString.resx文件。
   5.  添加一个新的名为ReportsPageTitle的字符串资源,并设置值为Reports。
  
   6.  保存并关闭ApplicationString.resx文件。
   7.  打开Reports.xaml文件,并添加如下XAML到Grid元素内。

 

ExpandedBlockStart.gif 代码
1  < scrollviewer  x:name ="PageScrollViewer"  style ="" >   
2       < stackpanel  x:name ="ContentStackPanel"  style ="" >   
3           < textblock  x:name ="HeaderText"  style =""  Text =" {Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}} " />   
4           < textblock  x:name ="ContentText"  style =""  Text ="Display reports based on user permissions" />    
5       </ stackpanel >
6  </ scrollviewer >

 

   8.  拖拽三个DataGrid控件到名为ContentStackPanel的stack面板内。当我们从工具栏中拖拽DataGrid控件时,会在项目中添加一个对System.Windows.Controls.Data程序集的应用,并在页面内添加System.Windows.Controls命名空间。
   9.  命名DataGrid控件为ProductsGrid、SalesOrdersGrid、CustomerGrid。
   10.  对每个DataGrid控件,设置Margin为5.

ExpandedBlockStart.gif 代码
 1  < navigation:page  x:class ="ExampleBusinessApplication.Views.Reports" >   
 2             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
 3             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
 4             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
 5             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
 6             xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  
 7             mc:Ignorable="d"  
 8             xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"  
 9             d:DesignWidth="640" d:DesignHeight="480"  
10             Title="Reports Page" >  
11       < grid  x:name ="LayoutRoot" >   
12           < scrollviewer  x:name ="PageScrollViewer"  style ="" >   
13               < stackpanel  x:name ="ContentStackPanel"  style ="" >   
14                   < textblock  x:name ="HeaderText"  style =""  Text =" {Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}} " />   
15                   < textblock  x:name ="ContentText"  style =""  Text ="Display reports based on user permissions" />   
16                   < data:datagrid  name ="ProductsGrid"  margin ="5" ></ data:datagrid >   
17                   < data:datagrid  name ="SalesOrdersGrid"  margin ="5" ></ data:datagrid >    
18                   < data:datagrid  name ="CustomersGrid"  margin ="5" ></ data:datagrid >   
19               </ stackpanel >
20           </ scrollviewer >
21       </ grid >
22  </ navigation:page >

 

   11.  打开Reports.xaml.cs或Reports.xaml.vb。
   12.  对c#,用using添加 System.Windows.Ria,System.Windows.Ria.ApplicationServices,ExampleBusinessApplication.Web, 和ExampleBusinessApplication.Resources命名空间。
   13.  创建AdventureWorksDomainService的名为context的实例,并创建一个名为numberOfRows的变量来保存检索的记录数量。

1  private  AdventureWorksDomainContext context  =   new  AdventureWorksDomainContext();   
2  int  numberOfRows  =   10 ;

 

   14.  添加一个名为LoadRestrictedReports的方法,这个方法调用GetSalesOrderHeaderQuery方法和 GetCustomerQuery方法。如果用户属于Managers角色,就显示对应的带结果的数据表格。
如果没有所需凭证的用户调用一个域操作时,域操作会返回一个异常。我们可以通过在调用域操作之前检查凭证来避免这种情况。

ExpandedBlockStart.gif 代码
 1  private   void  LoadRestrictedReports()   
 2  {   
 3      LoadOperation < salesorderheader >  loadSales  =  context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows));   
 4      SalesOrdersGrid.ItemsSource  =  loadSales.Entities;   
 5      SalesOrdersGrid.Visibility  =  System.Windows.Visibility.Visible;   
 6       if  (WebContext.Current.User.IsInRole( " Managers " ))   
 7      {   
 8          LoadOperation < customer >  loadCustomers  =  context.Load(context.GetCustomersQuery().Take(numberOfRows));   
 9          CustomersGrid.ItemsSource  =  loadCustomers.Entities;   
10          CustomersGrid.Visibility  =  System.Windows.Visibility.Visible;   
11      }   
12       else   
13      {   
14          CustomersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
15      }   
16  }

 

   15.  添加名为LoadReports的方法来检测是否用户已验证,如果已验证,就调用LoadRestricteReports方法。它还检索名为 DefaultRows的个性化属性,并对User对象的PropertyChanged事件添加事件处理程序。最后,对所有用户调用 GetProductsQuery方法。

ExpandedBlockStart.gif 代码
 1  private   void  LoadReports()   
 2  {   
 3       if  (WebContext.Current.User.IsAuthenticated)   
 4      {   
 5          numberOfRows  =  WebContext.Current.User.DefaultRows;   
 6          WebContext.Current.User.PropertyChanged  +=   new  System.ComponentModel.PropertyChangedEventHandler(User_PropertyChanged);   
 7          LoadRestrictedReports();   
 8      }   
 9       else   
10      {   
11          CustomersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
12          SalesOrdersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
13      }   
14      LoadOperation < product >  loadProducts  =  context.Load(context.GetProductsQuery().Take(numberOfRows));   
15      ProductsGrid.ItemsSource  =  loadProducts.Entities;   
16  }

 

   16.  对PropertyChanged事件添加事件处理程序,保证在DefaultRows属性改变时调用LoadReports方法。

1  void  User_PropertyChanged( object  sender, System.ComponentModel.PropertyChangedEventArgs e)   
2  {   
3       if  (e.PropertyName  ==   " DefaultRows " )   
4      {   
5          LoadReports();   
6      }   
7  }

 

   17.  为LoggedIn和LoggedOut事件添加事件处理方法,并根据用户凭证的状况装载或隐藏数据。

ExpandedBlockStart.gif 代码
1  void  Authentication_LoggedIn( object  sender, AuthenticationEventArgs e)   
2  {   
3      LoadReports();   
4  }   
5  void  Authentication_LoggedOut( object  sender, AuthenticationEventArgs e)   
6  {   
7      CustomersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
8      SalesOrdersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
9  }

 

   18.  在构造函数内添加下面的代码:

ExpandedBlockStart.gif 代码
1  public  Reports()   
2  {   
3      InitializeComponent();   
4       this .Title  =  ApplicationStrings.ReportsPageTitle;   
5      WebContext.Current.Authentication.LoggedIn  +=   new  System.EventHandler < authenticationeventargs > (Authentication_LoggedIn);   
6      WebContext.Current.Authentication.LoggedOut  +=   new  System.EventHandler < authenticationeventargs > (Authentication_LoggedOut);   
7      LoadReports();   
8  }

 


以下是完整代码

 

ExpandedBlockStart.gif 代码
 1  using  System;   
 2  using  System.Collections.Generic;   
 3  using  System.Linq;   
 4  using  System.Net;   
 5  using  System.Windows;   
 6  using  System.Windows.Controls;   
 7  using  System.Windows.Documents;   
 8  using  System.Windows.Input;   
 9  using  System.Windows.Media;   
10  using  System.Windows.Media.Animation;   
11  using  System.Windows.Shapes;   
12  using  System.Windows.Navigation;   
13  using  System.Windows.Ria;   
14  using  System.Windows.Ria.ApplicationServices;   
15  using  ExampleBusinessApplication.Web;   
16  using  ExampleBusinessApplication.Resources;   
17  namespace  ExampleBusinessApplication.Views   
18  {   
19       public   partial   class  Reports : Page   
20      {   
21           private  AdventureWorksDomainContext context  =   new  AdventureWorksDomainContext();   
22           int  numberOfRows  =   10 ;   
23           public  Reports()   
24          {   
25              InitializeComponent();   
26               this .Title  =  ApplicationStrings.ReportsPageTitle;   
27              WebContext.Current.Authentication.LoggedIn  +=   new  System.EventHandler < authenticationeventargs > (Authentication_LoggedIn);   
28              WebContext.Current.Authentication.LoggedOut  +=   new  System.EventHandler < authenticationeventargs > (Authentication_LoggedOut);   
29              LoadReports();   
30          }   
31           private   void  LoadReports()   
32          {   
33               if  (WebContext.Current.User.IsAuthenticated)   
34              {   
35                  numberOfRows  =  WebContext.Current.User.DefaultRows;   
36                  WebContext.Current.User.PropertyChanged  +=   new  System.ComponentModel.PropertyChangedEventHandler(User_PropertyChanged);   
37                  LoadRestrictedReports();   
38              }   
39               else   
40              {   
41                  CustomersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
42                  SalesOrdersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
43              }   
44              LoadOperation < product >  loadProducts  =  context.Load(context.GetProductsQuery().Take(numberOfRows));   
45              ProductsGrid.ItemsSource  =  loadProducts.Entities;   
46          }   
47           private   void  LoadRestrictedReports()   
48          {   
49              LoadOperation < salesorderheader >  loadSales  =  context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows));   
50              SalesOrdersGrid.ItemsSource  =  loadSales.Entities;   
51              SalesOrdersGrid.Visibility  =  System.Windows.Visibility.Visible;   
52               if  (WebContext.Current.User.IsInRole( " Managers " ))   
53              {   
54                  LoadOperation < customer >  loadCustomers  =  context.Load(context.GetCustomersQuery().Take(numberOfRows));   
55                  CustomersGrid.ItemsSource  =  loadCustomers.Entities;   
56                  CustomersGrid.Visibility  =  System.Windows.Visibility.Visible;   
57              }   
58               else   
59              {   
60                  CustomersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
61              }   
62          }   
63           void  Authentication_LoggedIn( object  sender, AuthenticationEventArgs e)   
64          {   
65              LoadReports();   
66          }   
67           void  Authentication_LoggedOut( object  sender, AuthenticationEventArgs e)   
68          {   
69              CustomersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
70              SalesOrdersGrid.Visibility  =  System.Windows.Visibility.Collapsed;   
71          }   
72           void  User_PropertyChanged( object  sender, System.ComponentModel.PropertyChangedEventArgs e)   
73          {   
74               if  (e.PropertyName  ==   " DefaultRows " )   
75              {   
76                  LoadReports();   
77              }   
78          }   
79      }   
80  }

 

   19.  运行解决方案。
   20.  点击Reports链接。注意到,当我们没登陆时,只有产品表显示在报告页面。
   21.  点击"登陆"链接,并以SalesUser登陆。会发现,产品和销售订单表显示出来。
  
   22.  登出并以CustomerManager登陆。会发现,三个表都显示了。
   23.  关闭web浏览器。

 

添加一个窗口来设置个性化属性
我们可以通过添加一个子窗口来允许用户编辑DefaultRows个性属性。当值改变后,我们调用SaveUser方法来把值保存到数据源。我们通过当前WebContext实例的User对象上的属性来检索当前的值。
   1.  在客户端,在Views文件夹中添加新项。
   2.  选择Silverlight Child Window模板,并命名为ProfileWindow.xaml。
  
   3.  点击"添加"按钮。
   4.  在ProfileWindow.xaml文件内,在Grid.RowDefinitions元素后添加XAML,来添加一个下拉列表选择要在报表中显示的行数。

ExpandedBlockStart.gif 代码
 1  < stackpanel orientation  =   " Horizontal "  grid.row  =   " 0 "   >   
 2       < textblock text  =   " Number of rows to display for reports:  "   ></ textblock  >   
 3       < combobox x:name  =   " defaultRows "  height  =   " 20 "  verticalalignment  =   " Top "   >   
 4           < comboboxitem content  =   " 1 "   ></  comboboxitem  >   
 5           < comboboxitem content  =   " 2 "   ></  comboboxitem  >   
 6           < comboboxitem content  =   " 3 "   ></  comboboxitem  >   
 7           < comboboxitem content  =   " 4 "   ></  comboboxitem  >   
 8           < comboboxitem content  =   " 5 "   ></  comboboxitem  >   
 9           < comboboxitem content  =   " 6 "   ></  comboboxitem  >   
10           < comboboxitem content  =   " 7 "   ></  comboboxitem  >   
11           < comboboxitem content  =   " 8 "   ></  comboboxitem  >   
12           < comboboxitem content  =   " 9 "   ></  comboboxitem  >   
13           < comboboxitem content  =   " 10 "   ></  comboboxitem  >   
14           < comboboxitem content  =   " 15 "   ></  comboboxitem  >   
15           < comboboxitem content  =   " 20 "   ></  comboboxitem  >   
16       </ combobox  >   
17  </ stackpanel  >

 

   5.  设置ChildWindow的Title属性为Select References。
   6.  在ProfileWindow.xaml.cs中,添加下面的代码来检索和设置个性化属性。

 

ExpandedBlockStart.gif 代码
 1  public   partial   class  ProfileWindow : ChildWindow  
 2  {  
 3       public  ProfileWindow()  
 4      {  
 5          InitializeComponent();  
 6           string  userDefaultRows  =  WebContext.Current.User.DefaultRows.ToString();  
 7           foreach  (ComboBoxItem cbi  in  defaultRows.Items)  
 8          {  
 9               if  (cbi.Content.ToString()  ==  userDefaultRows)  
10              {  
11                  defaultRows.SelectedItem  =  cbi;  
12                   break  ;  
13              }  
14          }  
15      }  
16 
17       private   void  OKButton_Click(  object  sender, RoutedEventArgs e)  
18      {  
19           int  newSelection  =   int  .Parse(defaultRows.SelectionBoxItem.ToString());  
20           if  (newSelection  !=  WebContext.Current.User.DefaultRows)  
21          {  
22              WebContext.Current.User.DefaultRows  =  newSelection;  
23              WebContext.Current.Authentication.SaveUser(  true  );  
24          }  
25           this  .DialogResult  =   true  ;  
26      }  
27 
28       private   void  CancelButton_Click(  object  sender, RoutedEventArgs e)  
29      {  
30           this  .DialogResult  =   false  ;  
31      } 
32  }

 

    7.  如果是VB,添加Imports命令引用System.Windows.Controls和System.Windows命名空间。
    8.  展开Views\Login文件夹,并打开LoginStatus.xaml文件。
    9.  添加一个指向profile文件的设置链接,在Logout按钮前添加下面的XAML  

ExpandedBlockStart.gif 代码
1  <  id ="highlighter_750424_clipboard"  title ="copy to clipboard"  type ="application/x-shockwave-flash"  width ="16"  height ="16"  src ="http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf"  id ="highlighter_750424_clipboard"  type ="application/x-shockwave-flash"  title ="copy to clipboard"  allowscriptaccess ="always"  wmode ="transparent"  flashvars ="highlighterId=highlighter_750424"  menu ="false"  src ="http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf"  height ="16"  width ="16" >
2 

 

1  <  button  x:name  = "SettingsButton"  click  = "SettingsButton_Click"  content  = "settings"  style  = ""  margin  = "0,0,0,0"   >
2  </  button  >   
3  <  textblock  text  = "  |  "  style  = ""   >   
4  </  textblock  >  
5 

 

   10.  在LoginStatus.xaml.cs文件内,为设置链接添加点击事件处理方法。

 

ExpandedBlockStart.gif 代码
1  < id ="highlighter_186072_clipboard"  title ="copy to clipboard"  type ="application/x-shockwave-flash"  width ="16"  height ="16"  src ="http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf"  id ="highlighter_186072_clipboard"  type ="application/x-shockwave-flash"  title ="copy to clipboard"  allowscriptaccess ="always"  wmode ="transparent"  flashvars ="highlighterId=highlighter_186072"  menu ="false"  src ="http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf"  height ="16"  width ="16" >

 

 

ExpandedBlockStart.gif 代码
1  private   void  SettingsButton_Click(  object  sender, RoutedEventArgs e)  
2  {  
3      ExampleBusinessApplication.Views.ProfileWindow settingsWindow  =   new  ExampleBusinessApplication.Views.ProfileWindow();  
4      settingsWindow.Show();  
5 
6 

 

   11.  运行解决方案。
   12.  以CustomerManager或SalesUser登陆,注意到在登陆状态栏,现在包含一个"设置"的链接。
   
   13.  点击"设置"链接,并设置默认的报表显示行数。
  
   14.  打开报表页面,会注意到DataGrid现在包含我们所选的行数。

 

 


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/blackant2/archive/2010/04/09/5466853.aspx

转载于:https://www.cnblogs.com/e_trock/archive/2010/06/05/1752286.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值