开发者论坛

 找回密码
 注册 (请使用非IE浏览器)
查看: 8949|回复: 6

XAF之自定义登录窗口(转)

[复制链接]

0

精华

161

贡献

57

赞扬

帖子
112
软币
1615
在线时间
263 小时
注册时间
2013-6-14
发表于 2013-6-19 17:19:36 | 显示全部楼层 |阅读模式
本帖最后由 linuxsc 于 2013-6-21 16:15 编辑

为了能在此坛子找到需要的资料。


当使用Standard Authentication验证类型,默认的登录窗口包含两个编辑框:用户名和密码。而本文讲述怎样自定义登录窗口,窗口包含一个下拉式列表选择company,另一个下拉式列表选择该company的employee,还有一个密码输入框。


自定义登录窗口,有以下两种方法:
a.继承AuthenticationStandardLogonParameters类,添加要在登录窗显示的额外属性。然后,可以用安全系统的LogonParameters属性访问特定的登录参数。然而,验证机制仍只使用用户名和密码。所以,若要对额外属性进行验证,需要继承AuthenticationStandard类并重写Authenticate方法。别忘了在Application Designer中指定自定义的登录参数类:

b.实现一个LogonParameters类(不从AuthenticationStandardLogonParameters类继承),添加额外属性。这种情况下,内置的AuthenticationStandard无法执行验证,所以还必须实现自定义的验证策略:继承AuthenticationBase类。
这里,我们使用第二种方法。
实现Employee和Company类
        由于Employee必须支持安全系统,故需要继承BasicUser类。
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using DevExpress.Persistent.BaseImpl;
  5. using DevExpress.Xpo;
  6. using DevExpress.Persistent.Base;
  7. using DevExpress.ExpressApp.Utils;
  8. using DevExpress.Data.Filtering;
  9. using System.ComponentModel;
  10. namespace AccessDatabaseFromLogonForm.Module {
  11.     [DefaultClassOptions(), System.ComponentModel.DefaultProperty("UserName")]
  12. public class Employee : SimpleUser {
  13.   private Company company;
  14.         public Employee(Session session)
  15.             : base(session) {
  16.         }
  17.        [Association("Company-Employees", typeof(Company))]
  18.         public Company Company {
  19.             get { return company; }
  20.    set {
  21.     SetPropertyValue("Company", ref company, value);
  22.    }
  23.         }
  24.     }
  25. }
复制代码
  1. using System;
  2. using DevExpress.Data.Filtering;
  3. using DevExpress.Xpo;
  4. using DevExpress.ExpressApp;
  5. using DevExpress.Persistent.Base;
  6. using DevExpress.Persistent.BaseImpl;
  7. using DevExpress.Persistent.Validation;
  8. using DevExpress.ExpressApp.Utils;

  9. namespace AccessDatabaseFromLogonForm.Module {
  10.     [DefaultClassOptions()]
  11.     public class Company : BaseObject {

  12.         public Company(Session session)
  13.             : base(session) {
  14.         }

  15.         private string name;
  16.         public string Name {
  17.             get { return name; }
  18.                         set {
  19.                                 SetPropertyValue("Name", ref name, value);
  20.                         }
  21.         }

  22.         [Association("Company-Employees", typeof(Employee))]
  23.         public XPCollection Employees {
  24.             get { return GetCollection("Employees"); }
  25.         }
  26.     }
  27. }
复制代码
实现MyLogonParameters类
  1. //实现ISupportResetLogonParameters接口,不必重启程序实现登录和注销
  2.     //在persistent类中,可以在属性setter中使用SetPropertyValue或OnChanged,但MyLogonParameters不是
  3.     //从BaseObject继承而来,故只能实现INotifyPropertyChanged接口
  4.         [NonPersistent]
  5.         public class MyLogonParameters : INotifyPropertyChanged, ISupportResetLogonParameters {
  6.         private IObjectSpace objectSpace;
  7.         //为避免在登录窗口新建Employee和Company,需要设置AvailableCompanies和AvailableUsers只读
  8.         private ReadOnlyCollection<Company> availableCompanies;
  9.         private XPCollection<Employee> availableUsers;

  10.         private Company company;
  11.         private Employee employee;
  12.         private string password;
  13.         private void OnPropertyChanged(string propertyName) {
  14.             if(PropertyChanged != null) {
  15.                 PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  16.             }
  17.         }
  18.         //显示的Employee要对于其Company,故为availableUsers添加了一个Criteria
  19.         private void RefreshAvailableUsers() {
  20.             if(availableUsers == null) {
  21.                 return;
  22.             }

  23.             availableUsers.Criteria = new BinaryOperator("Company", Company);

  24.             if(employee != null && availableUsers.IndexOf(employee) == -1) {
  25.                 Employee = null;
  26.             }
  27.             else {
  28.                 OnPropertyChanged("Employee");
  29.             }
  30.         }

  31.         [Browsable(false)]
  32.         public IObjectSpace ObjectSpace {
  33.             get { return objectSpace; }
  34.             set { objectSpace = value; }
  35.         }
  36.         //设置为ReadOnlyCollection,只读集合
  37.         [Browsable(false)]
  38.         public ReadOnlyCollection<Company> AvailableCompanies {
  39.             get {
  40.                 if (objectSpace == null) {
  41.                     throw new InvalidOperationException("objectSpace is null");
  42.                 }
  43.                 if (availableCompanies == null) {
  44.                                         availableCompanies = new ReadOnlyCollection<Company>(ObjectSpace.GetObjects<Company>(null));
  45.                                 }
  46.                 return availableCompanies;
  47.             }
  48.         }
  49.         [Browsable(false)]
  50.         public XPCollection<Employee> AvailableUsers {
  51.             get {
  52.                 if (availableUsers == null) {
  53.                                         availableUsers = (XPCollection<Employee>)ObjectSpace.GetObjects<Employee>();
  54.                     //设置availableUsers只读,不允许绑定的control增/删数据
  55.                     availableUsers.BindingBehavior = CollectionBindingBehavior.AllowNone;
  56.                     RefreshAvailableUsers();
  57.                 }
  58.                 return availableUsers;
  59.             }
  60.         }
  61.         //DataSourceProperty表示Company依赖于于属性AvailableCompanies,非常类似于PersistentAlias特性
  62.         //但PersistentAlias是对属性的高级”重命名“,DataSourceProperty是属性和数据绑定的关系
  63.         //ImmediatePostData表示当Company数据变化后,立即刷新UI
  64.         [DataSourceProperty("AvailableCompanies"), ImmediatePostData]
  65.         public Company Company {
  66.             get { return company; }
  67.             set {
  68.                 company = value;
  69.                 RefreshAvailableUsers();
  70.             }
  71.         }

  72.                 [DataSourceProperty("AvailableUsers"), ImmediatePostData]
  73.         public Employee Employee {
  74.             get { return employee; }
  75.             set {
  76.                 employee = value;
  77.                 OnPropertyChanged("Employee");
  78.             }
  79.         }

  80.         [PasswordPropertyText(true)]
  81.         public string Password {
  82.             get { return password; }
  83.             set { password = value; }
  84.         }

  85.         public void Reset() {
  86.             objectSpace = null;
  87.             availableCompanies = null;
  88.             availableUsers = null;
  89.             company = null;
  90.             employee = null;
  91.             password = null;
  92.         }
  93.         public event PropertyChangedEventHandler PropertyChanged;
  94.     }
复制代码
在Program.cs 文件中创建AvailableUsers 和 AvailableCompanies 的ObjectSpaced,并订阅CreateCustomLogonWindowObjectSpace事件
  1. static void Main() {
  2. //...
  3. AccessDatabaseFromLogonFormWindowsFormsApplication application =
  4. new AccessDatabaseFromLogonFormWindowsFormsApplication();
  5. application.CreateCustomLogonWindowObjectSpace +=
  6. new EventHandler<CreateCustomLogonWindowObjectSpaceEventArgs>(
  7. application_CreateCustomLogonWindowObjectSpace);
  8. //...
  9. }
  10. static void application_CreateCustomLogonWindowObjectSpace(object sender,
  11. CreateCustomLogonWindowObjectSpaceEventArgs e) {
  12. e.ObjectSpace = ((XafApplication)sender).CreateObjectSpace();
  13. ((MyLogonParameters)e.LogonParameters).ObjectSpace = e.ObjectSpace;
  14. }
复制代码
实现MyAuthentication类

       继承AuthenticationBase类,并重写以下方法:

Authenticate      //验证时调用。验证时比对数据库里的信息和logon parameter的值。
ClearSecuredLogonParameters      //清除logon parameters,防止在程序里访问它们,这样就隐藏了安全信息。
GetBusinessClasses      // 返回要添加到Application Model 中的bussiness classese。如果不返回LogonParameters,则不会在登录窗口中显示该视图。
AskLogonParametersViaUI       // 如果需要显示登录窗口获取用户的logon parameters,则返回true。若从其他地方获取logon parameters,如系统活动文件夹,则返回false。
LogonParameters          //返回代表当前logon parameters的对象。
IsLogoffEnabled         //是否允许“注销”操作。当前仅在ASP.NET可用。
  1. public class MyAuthentication : AuthenticationBase, IAuthenticationStandard {
  2.                 private MyLogonParameters logonParameters;
  3.         //创建一个LogonParameters对象
  4.                 public MyAuthentication() {
  5.                         logonParameters = new MyLogonParameters();
  6.                 }
  7.         //清除登录信息
  8.                 public override void ClearSecuredLogonParameters() {
  9.                         logonParameters.Password = "";
  10.                         base.ClearSecuredLogonParameters();
  11.                 }
  12.         //验证登录,正确则返回该登录用户
  13.                 public override object Authenticate(DevExpress.ExpressApp.IObjectSpace objectSpace) {
  14.                         if(logonParameters.Employee == null) {
  15.                                 throw new ArgumentNullException("User");
  16.                         }
  17.             //比对密码
  18.                         if(!logonParameters.Employee.ComparePassword(logonParameters.Password))
  19.                         {
  20.                             throw new AuthenticationException(logonParameters.Employee.UserName, "Wrong password");
  21.                         }
  22.                         return objectSpace.GetObject(logonParameters.Employee);
  23.                 }
  24.                 public override IList<Type> GetBusinessClasses() {
  25.                         return new Type[] { typeof(MyLogonParameters) };
  26.                 }
  27.                 public override bool AskLogonParametersViaUI {
  28.                         get {
  29.                                 return true;
  30.                         }
  31.                 }
  32.                 public override object LogonParameters {
  33.                         get { return logonParameters; }
  34.                 }

  35.                 public override bool IsLogoffEnabled {
  36.                         get { return true; }
  37.                 }
  38.         }
复制代码
将自定义的这些类传递给系统

          在Application Designer 中,只能添加内置的AuthenticationStandard策略,所以只能在代码中添加MyAuthentication类。WinForm工程里的Main方法中添加:
  1. AccessDatabaseFromLogonFormWindowsFormsApplication application = new AccessDatabaseFromLogonFormWindowsFormsApplication();
  2. application.Security = new SecuritySimple<Employee>(new MyAuthentication());
复制代码

评分

参与人数 5贡献 +5 赞扬 +4 收起 理由
nickcole + 1 感谢分享
maple + 1 很给力
seamone + 1 赞一个
happy2009 + 1 赞一个
羽叶 + 5 赞一个

查看全部评分

回复

使用道具 举报

0

精华

5

贡献

13

赞扬

帖子
113
软币
647
在线时间
71 小时
注册时间
2013-8-12
发表于 2013-12-16 13:59:22 | 显示全部楼层
很实用!谢谢分享
回复

使用道具 举报

0

精华

0

贡献

8

赞扬

帖子
26
软币
182
在线时间
14 小时
注册时间
2013-12-28
发表于 2013-12-28 06:12:06 | 显示全部楼层
这个好,谢谢楼主
回复

使用道具 举报

0

精华

0

贡献

0

赞扬

帖子
5
软币
65
在线时间
1 小时
注册时间
2014-10-15
发表于 2014-10-15 11:31:09 | 显示全部楼层
非常不错,小白的福音
回复

使用道具 举报

0

精华

0

贡献

0

赞扬

帖子
30
软币
152
在线时间
6 小时
注册时间
2015-4-3
发表于 2015-4-7 11:24:14 | 显示全部楼层
很好,受教了,谢谢!
回复

使用道具 举报

0

精华

0

贡献

0

赞扬

帖子
16
软币
106
在线时间
7 小时
注册时间
2016-1-7
发表于 2016-1-27 14:57:38 | 显示全部楼层
好帖,感谢分享
回复

使用道具 举报

Archiver|手机版|小黑屋|开发者网 ( 苏ICP备08004430号-2 )
版权所有:南京韵文教育信息咨询有限公司

GMT+8, 2024-4-25 19:29

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表