WPF MVVM - 简单登录到应用程序

时间:2011-08-18 22:02:37

标签: c# wpf user-interface mvvm

我正在继续学习WPF,并且目前专注于MVVM并使用Karl Shifflett的“MVVM In a Box”教程。但是有一个关于在views / viewmodels之间共享数据以及它如何在屏幕上更新视图的问题。附:我还没有报道过IOC。

下面是我在测试应用程序中的MainWindow的屏幕截图。它分为3个部分(视图),一个标题,一个带按钮的滑动面板,其余部分作为应用程序的主视图。应用程序的目的很简单,登录到应用程序。在成功登录后,登录视图应该被新视图(即OverviewScreenView)替换而消失,应用程序幻灯片上的相关按钮应该可见。

Main Window

我认为应用程序有2个ViewModel。一个用于MainWindowView,另一个用于LoginView,因为MainWindow不需要登录命令,所以我将它保持分开。

由于我尚未介绍IOC,我创建了一个单独的LoginModel类。它只包含一个属性“public bool LoggedIn”,以及一个名为UserLoggedIn的事件。

MainWindowViewModel构造函数注册到事件UserLoggedIn。现在在LoginView中,当用户在LoginView上单击Login时,它会在LoginViewModel上引发一个命令,如果正确输入用户名和密码,则会调用LoginModel并将LoggedIn设置为true。这会导致UserLoggedIn事件触发,在MainWindowViewModel中处理该事件以使视图隐藏LoginView并用不同的视图(即概览屏幕)替换它。

问题

Q1。明显的问题,就是这样登录正确使用MVVM。即控制流程如下。 LoginView - > LoginViewViewModel - > LoginModel - > MainWindowViewModel - > MainWindowView。

Q2。假设用户已登录,并且MainWindowViewModel已处理该事件。您将如何创建新视图并将其放在LoginView所在的位置,同样如何在不需要时处理LoginView。 MainWindowViewModel中是否存在类似“UserControl currentControl”的属性,该属性设置为LoginView或OverviewScreenView。

Q3。 MainWindow是否应该在visual studio设计器中设置LoginView。或者它应该留空,并以编程方式确认没有人登录,因此一旦加载了MainWindow,它就会创建一个LoginView并在屏幕上显示它。

下面的一些代码示例是否有助于回答问题

MainWindow的XAML

<Window x:Class="WpfApplication1.MainWindow"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="372" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <local:HeaderView Grid.ColumnSpan="2" />

        <local:ButtonsView Grid.Row="1" Margin="6,6,3,6" />

        <local:LoginView Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</Window>

MainWindowViewModel

using System;
using System.Windows.Controls;
using WpfApplication1.Infrastructure;

namespace WpfApplication1
{
    public class MainWindowViewModel : ObservableObject
    {
        LoginModel _loginModel = LoginModel.GetInstance();
        private UserControl _currentControl;

        public MainWindowViewModel()
        {
            _loginModel.UserLoggedIn += _loginModel_UserLoggedIn;
            _loginModel.UserLoggedOut += _loginModel_UserLoggedOut;
        }

        void _loginModel_UserLoggedOut(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        void _loginModel_UserLoggedIn(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }
    }
}

LoginViewViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Input;
using WpfApplication1.Infrastructure;

namespace WpfApplication1
{
    public class LoginViewViewModel : ObservableObject
    {
        #region Properties
        private string _username;
        public string Username
        {
            get { return _username; }
            set
            {
                _username = value;
                RaisePropertyChanged("Username");
            }
        }
        #endregion

        #region Commands

        public ICommand LoginCommand
        {
            get { return new RelayCommand<PasswordBox>(LoginExecute, pb => CanLoginExecute()); }
        }

        #endregion //Commands

        #region Command Methods
        Boolean CanLoginExecute()
        {
            return !string.IsNullOrEmpty(_username);
        }

        void LoginExecute(PasswordBox passwordBox)
        {
            string value = passwordBox.Password;
            if (!CanLoginExecute()) return;

            if (_username == "username" && value == "password")
            {
                LoginModel.GetInstance().LoggedIn = true;
            }
        }
        #endregion
    }
}

1 个答案:

答案 0 :(得分:28)