翻譯|使用教程|編輯:龔雪|2022-04-25 10:38:56.550|閱讀 211 次
概述:本系列內容將開始根據DevExpress WinForms MVVM創建示例應用程序,本文繼續講解如何創建登錄表單。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
從本文檔中,您將了解如何向應用程序添加登錄表單。在本節教程中著重討論了如何實現此任務,這基本上是附加應用程序功能的一部分。
4. 您還需要向主表單的ViewModel中添加一些代碼。由于主表單使用自動生成的MyDbContextViewModel 類,因此不建議將自定義代碼直接添加到其中 - 如果您需要再次調用Scaffolding Wizard,可以重新生成模型。相反,創建一個位于單獨文件中的部分類。 請注意,您必須將類構造函數從其原始文件移動到這個分部類。
C#
//MyDbContextViewModel.partial.cs public partial class MyDbContextViewModel { LoginViewModel loginViewModel; protected MyDbContextViewModel() : base(UnitOfWorkSource.GetUnitOfWorkFactory()) { loginViewModel = LoginViewModel.Create(); loginViewModel.SetParentViewModel(this); } protected IDialogService DialogService { get { return this.GetService<IDialogService>(); } } protected IMessageBoxService MessageService { get { return this.GetService<IMessageBoxService>(); } } public override void OnLoaded(MyDbContextModuleDescription module) { base.OnLoaded(module); Login(); } public virtual AppState State { get; set; } // Shows the Login View public void Login() { OnLogin(DialogService.ShowDialog(MessageButton.OKCancel, "Please enter you credentials", "LoginView", loginViewModel)); } //Occurs whenever the end-user clicks a dialog button void OnLogin(MessageResult result) { if(result == MessageResult.Cancel) State = AppState.ExitQueued; else { if(loginViewModel.IsCurrentUserCredentialsValid) State = AppState.Autorized; else Login(); } } protected void OnStateChanged() { this.RaiseCanExecuteChanged(x => x.Logout()); if(State == AppState.Autorized) Messenger.Default.Send<string>(loginViewModel.CurrentUser.Login); else Messenger.Default.Send<string>(string.Empty); } } public enum AppState { NotAutorized, Autorized, ExitQueued }
VB.NET
'MyDbContextViewModel.partial.vb Partial Public Class MyDbContextViewModel Private loginViewModel As LoginViewModel Protected Sub New() MyBase.New(UnitOfWorkSource.GetUnitOfWorkFactory()) loginViewModel = LoginViewModel.Create() loginViewModel.SetParentViewModel(Me) End Sub Protected ReadOnly Property DialogService() As IDialogService Get Return Me.GetService(Of IDialogService)() End Get End Property Protected ReadOnly Property MessageService() As IMessageBoxService Get Return Me.GetService(Of IMessageBoxService)() End Get End Property Public Overrides Sub OnLoaded(ByVal [module] As MyDbContextModuleDescription) MyBase.OnLoaded([module]) Login() End Sub Public Overridable Property State() As AppState ' Shows the Login View Public Sub Login() OnLogin(DialogService.ShowDialog(MessageButton.OKCancel, "Please enter you credentials", "LoginView", loginViewModel)) End Sub 'Occurs whenever the end-user clicks a dialog button Private Sub OnLogin(ByVal result As MessageResult) If result Is MessageResult.Cancel Then State = AppState.ExitQueued Else If loginViewModel.IsCurrentUserCredentialsValid Then State = AppState.Autorized Else Login() End If End If End Sub Protected Sub OnStateChanged() Me.RaiseCanExecuteChanged(Sub(x) x.Logout()) If State = AppState.Autorized Then Messenger.Default.Send(Of String)(loginViewModel.CurrentUser.Login) Else Messenger.Default.Send(Of String)(String.Empty) End If End Sub End Class Public Enum AppState NotAutorized Autorized ExitQueued End Enum
下面列出了 LoginViewModel 和兩個視圖(MainView 和 LoginView)的代碼。 當您的 ViewModel 準備就緒時,重新構建項目并將 MvvmContext 組件添加到登錄表單中,使用其智能標簽將 LoginViewModel 分配為此視圖的相關視圖模型。
C#
//LoginViewModel.cs public class LoginViewModel { public IEnumerable<string> LookUpUsers { get { return CredentialsSource.GetUserNames(); } } public virtual User CurrentUser { get; set; } public bool IsCurrentUserCredentialsValid { get; private set; } [DevExpress.Mvvm.DataAnnotations.Command(false)] public void Init() { this.CurrentUser = new User(); } public void Update() { IsCurrentUserCredentialsValid = CredentialsSource.Check(CurrentUser.Login, CurrentUser.Password); } public static LoginViewModel Create() { return ViewModelSource.Create<LoginViewModel>(); } } //MainView.cs public MainView() { InitializeComponent(); this.Opacity = 0; . . . } void InitializeNavigation() { . . . var fluentAPI = mvvmContext1.OfType<MyDbContextViewModel>(); fluentAPI.SetTrigger(x => x.State, (state) => { if(state == AppState.Autorized) Opacity = 1; /*Show Main Form*/ if(state == AppState.ExitQueued) Close(); // exit the app; }); } //LoginView.cs public partial class LoginView : DevExpress.XtraEditors.XtraUserControl { public LoginView() { InitializeComponent(); } protected override void OnLoad(System.EventArgs e) { base.OnLoad(e); var fluentAPI = mvvmContext1.OfType<LoginViewModel>(); fluentAPI.SetObjectDataSourceBinding(userBindingSource, x => x.CurrentUser, x => x.Update()); foreach(string item in mvvmContext1.GetViewModel<LoginViewModel>().LookUpUsers) LoginTextEdit.Properties.Items.Add(item); fluentAPI.ViewModel.Init(); } }
VB.NET
'LoginViewModel.vb Public Class LoginViewModel Public ReadOnly Property LookUpUsers() As IEnumerable(Of String) Get Return CredentialsSource.GetUserNames() End Get End Property Public Overridable Property CurrentUser() As User Private privateIsCurrentUserCredentialsValid As Boolean Public Property IsCurrentUserCredentialsValid() As Boolean Get Return privateIsCurrentUserCredentialsValid End Get Private Set(ByVal value As Boolean) privateIsCurrentUserCredentialsValid = value End Set End Property <DevExpress.Mvvm.DataAnnotations.Command(False)> Public Sub Init() Me.CurrentUser = New User() End Sub Public Sub Update() IsCurrentUserCredentialsValid = CredentialsSource.Check(CurrentUser.Login, CurrentUser.Password) End Sub Public Shared Function Create() As LoginViewModel Return ViewModelSource.Create(Of LoginViewModel)() End Function End Class 'MainView.vb Public Sub New() InitializeComponent() Me.Opacity = 0 . . . End Sub Private Sub InitializeNavigation() . . . Dim fluentAPI = mvvmContext1.OfType(Of MyDbContextViewModel)() fluentAPI.SetTrigger(Function(x) x.State, Sub(state) If state = AppState.Autorized Then Opacity = 1 End If If state = AppState.ExitQueued Then Close() End If End Sub) ' exit the app; - Show Main Form End Sub 'LoginView.vb Partial Public Class LoginView Inherits DevExpress.XtraEditors.XtraUserControl Public Sub New() InitializeComponent() End Sub Protected Overrides Sub OnLoad(ByVal e As System.EventArgs) MyBase.OnLoad(e) Dim fluentAPI = mvvmContext1.OfType(Of LoginViewModel)() fluentAPI.SetObjectDataSourceBinding(userBindingSource, Function(x) x.CurrentUser, Function(x) x.Update()) For Each item As String In mvvmContext1.GetViewModel(Of LoginViewModel)().LookUpUsers LoginTextEdit.Properties.Items.Add(item) Next item fluentAPI.ViewModel.Init() End Sub End Class
此代碼使用 OnLoaded 方法重載來顯示使用已注冊 DialogService 的對話框,為此Login方法調用服務的ShowDialog擴展方法,此方法將子 ViewModel 作為參數 - 將 LoginViewModel 類的新實例傳遞給它。創建這個實例很重要,不是使用 new 關鍵字,而是調用 ViewModelSource.Create<ViewModelType> 方法。或者,您可以調用 SetParentViewModel 方法為此實例設置父 ViewModel。
當最終用戶單擊任何登錄對話框的按鈕時,此消息結果將傳遞給 OnLogin 方法,該方法會準確檢查單擊了哪個按鈕。 如果最終用戶單擊 ‘Cancel’ 或關閉對話框,則應用程序將關閉。如果單擊‘OK’按鈕,應用程序將檢查 IsCurrentUserCredentialsValid 屬性,該屬性會在調用 Update 方法時自動刷新其值。如果輸入的憑據有效,將顯示主表單,否則將重新顯示登錄表單,這是通過為 State 屬性分配不同的值來完成的。 MainView 有一個觸發器,用于監視 State 屬性值的變化,并在它發生時做出相應的反應。
5. 前面的步驟足以實現具有最少功能的登錄表單。 但是,如果您的主視圖分配了關閉確認操作,可能會遇到某些問題。 例如,如果您關閉登錄表單,主表單(由于未輸入有效憑據而變得透明)也將嘗試自行關閉。 這將顯示確認消息,如果您單擊‘Cancel’按鈕,表格將保留,但您將看不到它。 要克服此類問題,請刪除表單關閉操作(如果有)并添加以下代碼。
C#
//MainView.cs fluentAPI.WithEvent<FormClosingEventArgs>(this, "FormClosing") .EventToCommand(x => x.OnClosing(null), new Func<CancelEventArgs, object>((args) => args)); //MyDbContextViewModel.partial.cs public override void OnClosing(CancelEventArgs cancelEventArgs) { base.OnClosing(cancelEventArgs); if(!cancelEventArgs.Cancel) { if(State == AppState.Autorized && MessageService.ShowMessage("Do you really want to close the application?", "Confirm", MessageButton.YesNo) == MessageResult.No) cancelEventArgs.Cancel = true; } }
VB.NET
'MainView.vb fluentAPI.WithEvent(Of FormClosingEventArgs)(Me, "FormClosing").EventToCommand(Function(x) x.OnClosing(Nothing), New Func(Of CancelEventArgs, Object)(Function(args) args)) 'MyDbContextViewModel.partial.vb public override void OnClosing(CancelEventArgs cancelEventArgs) MyBase.OnClosing(cancelEventArgs) If Not cancelEventArgs.Cancel Then If State = AppState.Autorized AndAlso MessageService.ShowMessage("Do you really want to close the application?", "Confirm", MessageButton.YesNo) = MessageResult.No Then cancelEventArgs.Cancel = True End If End If
此代碼檢查當前的 State 屬性值,僅在授權通過時顯示確認消息。 如果最終用戶尚未登錄并決定關閉應用程序,則不會顯示任何確認信息。 這就是為什么 State 屬性不是布爾值,而是接受自定義 AppState 枚舉器的值的原因。 可能存在三種應用狀態:
6. 您的登錄表單現已準備就緒。可以通過為密碼編輯器設置特定的 RepositoryItemTextEdit.PasswordChar 來裝飾它,在主表單上反映登錄用戶的名稱,并將按鈕添加到主視圖的網格控件中,以便您重新登錄等,下面的代碼說明了 怎么做。
C#
//LoginView.cs PasswordTextEdit.Properties.PasswordChar = '*'; //MyDbContextViewModel.partial.cs protected void OnStateChanged() { this.RaiseCanExecuteChanged(x => x.Logout()); if(State == AppState.Authorized) Messenger.Default.Send<string>(loginViewModel.CurrentUser.Login); else Messenger.Default.Send<string>(string.Empty); } public void Logout() { State = AppState.ExitQueued; System.Diagnostics.Process.Start(System.Windows.Forms.Application.ExecutablePath); } public bool CanLogout() { return State == AppState.Authorized; } //MainView.cs Messenger.Default.Register<string>(this, OnUserNameMessage); fluentAPI.BindCommand(biLogout, x => x.Logout()); void OnUserNameMessage(string userName) { if(string.IsNullOrEmpty(userName)) this.Text = "Expenses Application"; else this.Text = "Expenses Application - (" + userName + ")"; }
VB.NET
'LoginView.vb PasswordTextEdit.Properties.PasswordChar = "*"c 'MyDbContextViewModel.partial.vb protected void OnStateChanged() Me.RaiseCanExecuteChanged(Sub(x) x.Logout()) If State = AppState.Authorized Then Messenger.Default.Send(Of String)(loginViewModel.CurrentUser.Login) Else Messenger.Default.Send(Of String)(String.Empty) End If public void Logout() State = AppState.ExitQueued System.Diagnostics.Process.Start(System.Windows.Forms.Application.ExecutablePath) public Boolean CanLogout() Return State = AppState.Authorized 'MainView.vb Messenger.Default.Register(Of String)(Me, AddressOf OnUserNameMessage) fluentAPI.BindCommand(biLogout, Function(x) x.Logout()) void OnUserNameMessage(String userName) If String.IsNullOrEmpty(userName) Then Me.Text = "Expenses Application" Else Me.Text = "Expenses Application - (" & userName & ")" End If
DevExpress WinForm擁有180+組件和UI庫,能為Windows Forms平臺創建具有影響力的業務解決方案。DevExpress WinForms能完美構建流暢、美觀且易于使用的應用程序,無論是Office風格的界面,還是分析處理大批量的業務數據,它都能輕松勝任!
更多產品正版授權詳情及優惠,歡迎咨詢
DevExpress技術交流群6:600715373 歡迎一起進群討論
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都網