WPF運用MVVM模式的登錄Demo


  初學WPF,網上資料都說用MVVM模式開發WPF程序是最好的,就順帶了解了下MVVM,不過實踐的時候遇到個小問題:ViewModel中要彈出提示時該如何處理,是在ViewModel中寫彈出框還是怎么滴?登錄成功后,關閉登錄窗口打開主窗口,這樣的邏輯該寫到哪,View還是ViewModel中控制?

  在我的理解中,ViewModel中是不知道具體的View的,所以在ViewModel中去關閉View或者打開某個View好像不是很好。於是想到在ViewModel中定義事件,在View中對ViewModel中的事件進行處理。可是如果要彈出詢問框,又該如何處理?望園里的大神門指點12。

  LoginDemo下載

  自定義登錄控件:

LoginControl.xaml
<UserControl x:Class="LoginDemo.Views.LoginControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:v="clr-namespace:LoginDemo.Views"
             mc:Ignorable="d" 
             d:DesignHeight="160" d:DesignWidth="341">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="80"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Label Name="lblAccount" Content="賬號" Style="{StaticResource TipsLabel}"
               Grid.Row="0" Grid.Column="0"></Label>
        <Label Name="lblPassword" Content="密碼" Style="{StaticResource TipsLabel}"
               Grid.Row="1" Grid.Column="0"></Label>
        <TextBox Name="txtAccount" Style="{StaticResource InputBox}"
                 Grid.Row="0" Grid.Column="1"
                 Text="{Binding LoginID}"></TextBox>
        <PasswordBox Name="txtPassword" Style="{StaticResource InputBox}"
                     Grid.Row="1" Grid.Column="1"
                     v:PasswordBoxHelper.Attach="True"
                     v:PasswordBoxHelper.Password="{Binding Password, Mode=TwoWay}"></PasswordBox>
        <StackPanel Grid.Row="2" Grid.Column="1" Style="{StaticResource CommandPanel}">
            <Button Name="btnLogin" Content="登錄" Command="{Binding Login}" Style="{StaticResource LoginCommand}"></Button>
            <Button Name="btnClose" Content="退出" Command="Close" Style="{StaticResource CloseCommand}"></Button>
        </StackPanel>
    </Grid>
</UserControl>

  由於PasswordBox.Password是不支持Binding的,所以在網上找了個輔助綁定的代碼,這里就不貼出來了。

ILoginViewModel
    public interface ILoginViewModel
    {
        string LoginID { get; set; }
        string Password { get; set; }
        ICommand Login { get; }
    }
LoginViewModel
    public class LoginViewModel : ObservableObject, ILoginViewModel
    {
        private LoginModel loginModel = new LoginModel();
        private ICommand _LoginCommand;

        public event EventHandler LoginSuccess;
        public event TipsEventHandler LoginFailed;

        protected virtual void OnLoginSuccess()
        {
            var handler = this.LoginSuccess;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        protected virtual void OnLoginFailed(string tips)
        {
            var handler = this.LoginFailed;
            if (handler != null) handler(this, new TipsEventArgs(tips));
        }

        public string LoginID
        {
            get { return this.loginModel.LoginID; }
            set
            {
                this.loginModel.LoginID = value;
                RaisePropertyChanged(() => LoginID);
            }
        }

        public string Password
        {
            get { return this.loginModel.Password; }
            set
            {
                this.loginModel.Password = value;
                RaisePropertyChanged(() => Password);
            }
        }

        public ICommand Login
        {
            get
            {
                if (this._LoginCommand == null)
                {
                    this._LoginCommand = new CommandProxy(LoginAction);
                }
                return this._LoginCommand;
            }
        }

        private void LoginAction(object parameter)
        {
            if (this.LoginID != "admin" ||
                this.Password != "123")
            {
                OnLoginFailed("用戶名或密碼錯誤!\n正確的用戶名是admin\n正確的密碼是123");
                return;
            }
            OnLoginSuccess();
        }
    }

  登錄界面:

Login.xaml
<Window x:Class="LoginDemo.Views.Login"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:LoginDemo.Views"
        xmlns:vm="clr-namespace:LoginDemo.ViewModels"
        Title="登錄" Height="303" Width="470">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="30"/>
        </Grid.ColumnDefinitions>
        <c:LoginControl x:Name="loginControl" Grid.Row="1" Grid.Column="1">
            <c:LoginControl.DataContext>
                <vm:LoginViewModel
                                   LoginID="admin1" Password="123"
                                   LoginSuccess="LoginViewModel_LoginSuccess"
                                   LoginFailed="LoginViewModel_LoginFailed"/>
            </c:LoginControl.DataContext>
        </c:LoginControl>
    </Grid>
</Window>
Login.xaml.cs
    /// <summary>
    /// Login.xaml 的交互邏輯
    /// </summary>
    public partial class Login : Window
    {
        public Login()
        {
            InitializeComponent();

            // 如果不添加這行代碼,則退出按鈕是不可用的,因為內置的Close命令是沒有實現的,要自己實現
            this.CommandBindings.Add(new CloseCommandBindingProxy(this));
        }

        private void LoginViewModel_LoginSuccess(object sender, EventArgs e)
        {
            MainWindow mainWindow = new MainWindow();
            this.Close();
            mainWindow.ShowDialog();
        }

        private void LoginViewModel_LoginFailed(object sender, ViewModels.TipsEventArgs e)
        {
            MessageBox.Show(e.Tips, "提示");
        }
    }

  登錄失敗、登錄成功的處理不知道這樣行不行,現在就糾結在View與ViewModel的這種交互上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM