【问题标题】:Relation between Model View and View model in WPFWPF中模型视图和视图模型之间的关系
【发布时间】:2016-07-22 06:22:06
【问题描述】:

我已经使用 MVVM 创建了登录身份验证,它运行良好。这就是我所做的:

MainWinodw.xaml

  <Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVis" />
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0">UserName:</TextBlock>
    <TextBlock Grid.Row="1" Grid.Column="0">Password:</TextBlock>
    <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    <Label Grid.Row="3" Grid.ColumnSpan="2" Visibility="{Binding isAuthenticated, Converter={StaticResource BoolToVis}}">
        User has been authenticated
    </Label>
    <Label Grid.Row="3" Grid.ColumnSpan="2" Visibility="{Binding LoginFail, Converter={StaticResource BoolToVis}}">
         Please enter valid  UserName and Password
    </Label>

    <Button Grid.Row="2" Grid.Column="1" Content="Authenticate" Command="{Binding LoginCommand}" Margin="3" Width="100" HorizontalAlignment="Right" />
</Grid>

UserViewModel.cs

public class LoginViewModel : INotifyPropertyChanged
{
    private bool _isAuthenticated;
    public bool isAuthenticated
    {
        get { return _isAuthenticated; }
        set
        {
            if (value != _isAuthenticated)
            {
                _isAuthenticated = value;
                OnPropertyChanged("isAuthenticated");
            }
        }
    }

    private bool _loginFail;
    public bool LoginFail
    {
        get { return _loginFail; }
        set
        {
            if (value != _loginFail)
            {
                _loginFail = value;
                OnPropertyChanged("LoginFail");
            }
        }
    }

    private string _username;
    public string UserName
    {
        get { return _username; }
        set
        {
            _username = value;
            OnPropertyChanged("UserName");
        }
    }

    private string _password;
    public string Password
    {
        get { return _password; }
        set
        {
            _password = value;
            OnPropertyChanged("Password");
        }
    }

    public ICommand LoginCommand
    {
        get { return new RelayCommand(param => this.Login()); }
    }

    public void Login()
    {
        //TODO check username and password vs database here.
        //If using membershipprovider then just call Membership.ValidateUser(UserName, Password)
        //if (!String.IsNullOrEmpty(UserName) && !String.IsNullOrEmpty(Password))
        //    isAuthenticated = true;
        isAuthenticated = LoginDataLayer.AuthenticateUser(UserName, Password);
        if(isAuthenticated == true)
        {
            LoginFail = false;
        }
        else
        {
            LoginFail = true;
        }

    }

    #region INotifyPropertyChanged Methods

    public void OnPropertyChanged(string propertyName)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, args);
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

这工作正常。但正如我所说,我是 MVVM 的新手。我也在 viewmodel 中编写模型代码。在意识到我的错误后,我尝试像这样分离模型和视图模型代码:

UserModel.cs

 public  class UserModel : INotifyPropertyChanged
{
    private bool _isAuthenticated;
    public bool isAuthenticated
    {
        get { return _isAuthenticated; }
        set
        {
            if (value != _isAuthenticated)
            {
                _isAuthenticated = value;
                OnPropertyChanged("isAuthenticated");
            }
        }
    }

    private bool _loginFail;
    public bool LoginFail
    {
        get { return _loginFail; }
        set
        {
            if (value != _loginFail)
            {
                _loginFail = value;
                OnPropertyChanged("LoginFail");
            }
        }
    }

    private string _username;
    public string UserName
    {
        get { return _username; }
        set
        {
            _username = value;
            OnPropertyChanged("UserName");
        }
    }

    private string _password;
    public string Password
    {
        get { return _password; }
        set
        {
            _password = value;
            OnPropertyChanged("Password");
        }
    }

    #region INotifyPropertyChanged Methods

    public void OnPropertyChanged(string propertyName)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, args);
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

UserViewModel.cs

public void Login()
    {
        UserModel obj = new UserModel();


        obj.isAuthenticated = LoginDataLayer.AuthenticateUser(obj.UserName,obj. Password);
        if(obj.isAuthenticated == true)
        {
           obj.LoginFail = false;
        }
        else
        {
            obj.LoginFail = true;
        }

    }

但我得到 obj.username 为空。那么任何人都可以帮助我如何在视图模型中获取模型属性以及它如何更新。请帮忙。 谢谢

【问题讨论】:

  • 我不认为你不能把你的两个逻辑放在一起。在 ViewModel 中拥有这些方法不是问题。你可以继续你的方法
  • 如果您的视图绑定到模型,当文本框显示该值时,它正在通过 getter 访问。尝试调试并查看它是否在 getter 中停止。如果没有,您的绑定不起作用。
  • 当模型已经为其所有属性实现了 INotifyPropertyChanged 时,在视图模型中复制所有这些没有多大意义。这里最简单的方法是从模型中派生视图模型,例如public class UserViewModel : UserModel { ... },并仅定义模型中尚未定义的那些属性和方法。
  • 那么正确的方法是什么?如果您的视图访问来自 2 个不同模型的数据怎么办?
  • 考虑拥有一个不实现 INotifyPropertyChanged 的​​模型,例如生成的 DAO。然后你会使用delegation/composition 而不是继承。 MVVM 没有定义“首选”或“正确”的方式。

标签: wpf mvvm


【解决方案1】:

在我看来,您的视图数据上下文是 viewModel,但属性在模型上。使您的 UserModel 可从 View Model 访问,如下所示:

视图模型:

private UserModel _userModel;
public UserModel userModel
{
    get { return _userModel; }
    set
    {
        _userModel = value;
        OnPropertyChanged("userModel");
    }
}

查看:

<TextBox Text="{Binding userModel.UserName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

【讨论】:

    猜你喜欢
    • 2011-09-03
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 2014-07-10
    相关资源
    最近更新 更多