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