不触发OnPropertyChanged

时间:2020-10-19 18:39:57

标签: c# wpf mvvm

我是MVVM的新手,我尝试从2个文本框中检索用户名和密码。但是,即使我具有UpdateSourceTriggered = PropertyChanged,也不会触发OnPropertyChanged。这是代码。我还尝试了使用RelayCommand类,该类使用委托Action <>和Func <>,但都没有用。

LogInCommand.cs

using LibraryApp.ViewModels;
using System;
using System.Windows.Input;

namespace LibraryApp.Commands
{
    public class LogInCommand : ICommand
    {
        private LogInViewModel _logInViewModel;

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public LogInCommand(LogInViewModel logInViewModel)
        {
            _logInViewModel = logInViewModel;
        }

        public bool CanExecute(object parameter) => _logInViewModel.CanUpdate;

        public void Execute(object parameter) => _logInViewModel.Execute();
    }
}

LogInModel.cs

using System.ComponentModel;

namespace LibraryApp.Models
{
    public class LogInModel : INotifyPropertyChanged
    {
        private string _strUsername;
        private string _strPassword;

        public string Username 
        {
            get { return _strUsername; }
            set {
                _strUsername = value;
                OnPropertyChanged(Username);
            }
        }

        public string Password
        {
            get { return _strPassword; }
            set
            {
                _strPassword = value;
                OnPropertyChanged(Password);
            }
        }

        public LogInModel(string strUsername, string strPassword)
        {
            Username = strUsername;
            Password = strPassword;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string property)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
        }

        #endregion
    }
}

LogInViewModel.cs

using LibraryApp.Commands;
using LibraryApp.Models;
using LibraryApp.Models.DatabaseModel;
using LibraryApp.Views;
using System.Linq;
using System.Windows;
using System.Windows.Input;

namespace LibraryApp.ViewModels
{
    public class LogInViewModel 
    {
        private LogInModel _user;
        private LibraryEntities _database;

        public LogInModel User
        {
            get { return _user; }
        }
        public bool CanUpdate
        {
            get
            {
                if (User == null)
                {
                    return false;
                }
                return !(string.IsNullOrWhiteSpace(User.Username) && string.IsNullOrWhiteSpace(User.Password));
            }
        }

        public ICommand SubmitCommand { get; set; }

        public void Execute()
        {
            if (IsUserInDatabase())
            {
                UserPage userPage = new UserPage();
                userPage.Show();

            }
            else
            {
                MessageBox.Show("Username or password are incorrect.");
            }
        }

        public LogInViewModel()
        {
            _user = new LogInModel("admin", "d7x2rt58");
            _database = new LibraryEntities();
            SubmitCommand = new LogInCommand(this);
        }

        public bool IsUserInDatabase()
        {
            if (_database.BookKeepers.First(it => it.Username == User.Username && it.Password == User.Password) != null)
            {
                return true;
            }
            return false;
        }
    }
}

LogIn.xaml

<Window x:Class="LibraryApp.Views.LogIn"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:LibraryApp.Views"
        mc:Ignorable="d"
        Title="LogIn" Height="150" Width="300" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
    <Grid Margin="5">

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Grid.Column="1" Content="Log In" HorizontalAlignment="Center"/>
        <Label Grid.Row="1" Grid.Column="0" Content="Username"/>
        <Label Grid.Row="2" Grid.Column="0" Content="Password"/>

        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding LogInModel.Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding LogInModel.Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <Button Grid.Row="3" Grid.Column="2" Command="{Binding SubmitCommand}" Content="Log In"/>
    </Grid>
</Window>

LogIn.xaml.cs

using LibraryApp.ViewModels;
using System.Windows;

namespace LibraryApp.Views
{
    /// <summary>
    /// Interaction logic for LogIn.xaml
    /// </summary>
    public partial class LogIn : Window
    {
        public LogIn()
        {
            InitializeComponent();
            LogInViewModel logInViewModel = new LogInViewModel();
            DataContext = logInViewModel;
        }
    }
}

UserPage.xaml

<Window x:Class="LibraryApp.Views.UserPage"
      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:local="clr-namespace:LibraryApp.Views"
      mc:Ignorable="d" 
      Height="450" Width="800"
      Title="UserPage">

    <Grid>
        <Label Content="Welcome" HorizontalAlignment="Center" Margin="0,50,0,0" VerticalAlignment="Top" Height="52" Width="134" FontSize="30"/>
        <Button Content="Add book" HorizontalAlignment="Left" Margin="104,145,0,0" VerticalAlignment="Top" Width="75"/>
        <Button Content="Borrow book" HorizontalAlignment="Left" Margin="104,190,0,0" VerticalAlignment="Top" Width="75"/>
        <Button Content="Delete book" HorizontalAlignment="Left" Margin="104,242,0,0" VerticalAlignment="Top" Width="75"/>
        <Button Content="Add user" HorizontalAlignment="Left" Margin="314,145,0,0" VerticalAlignment="Top" Width="75"/>
        <Button Content="Delete user" HorizontalAlignment="Left" Margin="314,195,0,0" VerticalAlignment="Top" Width="75"/>
        <Button Content="Search" HorizontalAlignment="Left" Margin="314,242,0,0" VerticalAlignment="Top" Width="75"/>
        <Button Content="Back" HorizontalAlignment="Left" Margin="648,360,0,0" VerticalAlignment="Top" Width="75"/>
    </Grid>
</Window>

UserPage.xaml.cs

using System.Windows;

namespace LibraryApp.Views
{
    /// <summary>
    /// Interaction logic for UserPage.xaml
    /// </summary>
    public partial class UserPage : Window
    {
        public UserPage()
        {
            InitializeComponent();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

欢迎来到SO。首先,尝试将您发布的代码量限制为仅必要的部分。当您张贴文字墙时,人们会迅速跳过您的问题。

要回答您的问题...

LogInModelUsername的设置器中的Password中,您通过传递属性的值而不是属性名称本身来引发事件:

public string Username 
{
    get { return _strUsername; }
    set
    {
        _strUsername = value;
        OnPropertyChanged(Username);
    }
}

相反,您应该传递属性本身的名称:

public string Username 
{
    get { return _strUsername; }
    set
    {
        _strUsername = value;
        OnPropertyChanged(nameof(Username));
        // The above is the same as:
        // OnPropertyChanged("Username");
    }
}