OnPropertyChanged not triggered



我是MVVM的新手,我试图从两个文本框中检索用户名和密码。但是,即使UpdateSourceTriggered=PropertyChanged,也不会触发OnPropertyChanged。这是代码。我还尝试了一个类RelayCommand,它使用delegates Action<gt;并且Func<gt;但两者都不起作用。

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;
}
}
}

用户页面.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();
}
}
}

欢迎使用SO。首先,尽量将发布的代码量限制在必要的部分。当你贴出一堵文字墙时,人们会很快跳过你的问题。

要回答您的问题。。。

UsernamePassword的setter中的LogInModel中,您通过传入属性值而不是属性名称本身来引发事件:

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");
}
}

最新更新