How to check two passwords for identity so that an error can be displayed ( validation rule or implementation of IDataErrorInfo )?

  • Do you mean string comparison? - VladD
  • I guess, yes. It is important that I can display the error using Validation.ErrorTemplate - Sergеu Isupov
  • one
    Well, let your viewmodel implement IDataErrorInfo . codearsenal.net/2012/06/… - VladD
  • one
    Wait, where did the Entity Framework come from? The model is not at all interesting to us, it doesn’t interest the viewmodel. And why won't the solution IDataErrorInfo with IDataErrorInfo ? - VladD
  • one
    You do not need to compare text boxes. Viewmodel should have 2 fields - "password" and "confirmation". If they change, if they do not match, generate an error event. - Oleg Nechitailo

3 answers 3

In the comments to the question the idea itself was explained to you. And I will try on an example. For starters, the behavior you want to achieve is best solved in WPF using the MVVM pattern. I'll give an excerpt

The MVVM pattern is divided into three parts:

Model (eng. Model) , just as in classical MVC, Model is the fundamental data necessary for the application to work.

A view is a graphical interface, that is, a window, buttons, etc. A view is a subscriber to an event of a change in the values ​​of properties or commands provided by the View Model. If a property has changed in the View Model, it notifies all subscribers of this, and the View, in turn, requests the updated value of the property from the View Model. In case the user acts on any element of the interface, the View invokes the corresponding command provided by the View Model.

The view model (English ViewModel) is, on the one hand, an abstraction of the View, and on the other hand, provides a wrapper for data from the Model that is to be linked. That is, it contains a Model that is converted to a View, and also contains commands that the View can use to influence the Model.

In total, we get that the EntityFramework classes are models (Model), various controls are views (View). We lack the “layer” between them, called the view model (ViewModel), which will wrap our model so that the View can work with it.

Well, let's get started

Let our model look something like this:

 class User { public int Id { get; set; } public string Login { get; set; } public string Password { get; set; } } 

Here, I think everything is clear. Now for this model we need a ViewModel. First, it must provide the model data for the View (while controlling the correctness of these same data), and second, implement the business logic provided through the teams.

In WPF, a ViewModel must implement the INotifyPropertyChanged interface in order for View to learn about data changes in the ViewModel. For good, it's better to take some kind of framework, for example MVVM Light , there already is a base class for ViewModel with the necessary functionality. I will give an example without him.

For simplicity, I will do without any regard for security, the passwords will be stored openly in string form, and entered into the usual TextBox . For good, the password hashes should be stored, and the input should be done via the PasswordBox. I will also use the ValieationRule - I like this approach more.

 public class UserVM : INotifyPropertyChanged { private readonly User _user; // Модель, которую будем оборачивать // т.к. поле повторного ввода не нужно модели, мы его вводим тут private string _repeatPassword; public UserVM(User user) { if (user == null) throw new ArgumentNullException("User model"); _user = user; } // Реализуем интерфейс INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; // Вспомогательная функция, для генерации события изменения свойства public void RaisePropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public string Login { get { return _user.Login; } set { if (string.IsNullOrEmpty(value)) // Не разрешаем указать пустой логин throw new ArgumentNullException(); if (_user.Login == value) return; _user.Login = value; RaisePropertyChanged("Login"); // Сообщаем о том, что поле изменилось } } public string Password { get { return _user.Password; } set { if (string.IsNullOrEmpty(value)) // Не разрешаем указать пустой пароль throw new ArgumentNullException(); if (_user.Password == value) return; _user.Password = value; RaisePropertyChanged("Password"); // Сообщаем о том, что поле изменилось } } public string RepeatPassword { get { return _repeatPassword; } set { if (string.IsNullOrEmpty(value)) // Не разрешаем указать пустой пароль throw new ArgumentNullException(); if (value != Password) // Тут, собственно,и выполняется проверка на совпадение. Если не совпало, генерируем исключение throw new ArgumentException("Пароли не совпали"); if (_repeatPassword == value) return; _repeatPassword = value; RaisePropertyChanged("RepeatPassword"); // Сообщаем о том, что поле изменилось } } // Еще много-много кода } 

Now we describe View, at the same time without forgetting to put down ValidatesOnExceptions . I will describe only the fields themselves:

 <Grid DataContext="{Binding ...}"> <Grid.RowsDefinition> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowsDefinition> <Grid.ColumnsDefinition> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnsDefinition> <TextBlock Grid.Row="0" Grid.Column="0" Text="Логин: "/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Login, ValidatesOnExceptions=True}"/> <TextBlock Grid.Row="0" Grid.Column="0" Text="Пароль: "/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Password, ValidatesOnExceptions=True}"/> <TextBlock Grid.Row="0" Grid.Column="0" Text="Повторите пароль: "/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=RepeatPassword, ValidatesOnExceptions=True}"/> </Grid> 

That's all. It is also possible for TextBoxes to describe the ErrorTemplate. Googling on this topic, there is enough information in the network.

PS Wrote "on the knee", so there may be inaccuracies

  • if Model is just data, ViewModel is UI-logic, then where is the business logic? is it not easier to implement INotifyPropertyChanged in the User class, and not to create a wrapper class for User? - Stack
  • User is a model; it should not know anything about the ViewModel or the View at all. > is it not easier to implement INotifyPropertyChanged in the User class, and not to create a wrapper class for User? At first glance it may seem simpler, but as soon as the project starts to grow simplicity turns into a splinter in a famous place - Donil
  • "User is a model" - i.e. just data. UserVM is a ViewModel that implements UI logic. but where is the business logic? for example, where to implement a simple business rule: if user.Password.Length <6 then throw "too short". - Stack
  • In ViewModel, there is business logic. UI logic, if desired, can be implemented only in View, there are triggers. But usually a composition is made - part of the UI-logic in the ViewModel, part in the View. Some rules of UI logic are easier to implement in ViewModel - Donil
  • "In the ViewModel, there is business logic." - and since ViewModel and View are strongly connected, it turns out that the business logic is also tied to the UI, and is intolerable. those. The model and business logic from a wpf application cannot simply be taken and transferred, for example, to asp.net mvc. - Stack

Solution in javascript (first check on the client and then on the server)

 function strcmp(a, b) { if (a.toString() < b.toString()) return -1; if (a.toString() > b.toString()) return 1; return 0; } function textOK(e) { return (e.value != "" || e.value === undefined || e.value == null) ? true : false; } function validatepasswodr() { var _rsp = document.getElementById('rsp'); var a = document.getElementById('tbPassword').value; var b = document.getElementById('tbRePassword').value; var _tbRePassword = document.getElementById('tbRePassword'); var filter = /^[a-zA-Zа-яА-Я0-9-~!@#$%^&?*]{6,20}$/; if (textOK(_tbRePassword) == true) { if (!filter.test(_tbRePassword.value)) { _rsp.style.display = 'block'; _rsp.style.color = 'red'; _rsp.innerHTML = 'Укажите валидный пароль от 6 до 20 символов. Допустимы только буквы, цифры и спецсимволы:-~!@#$%^&?* А вы указали: "<b>' + _tbRePassword.value + '</b>"'; return; if (strcmp(a, b) == -1 || strcmp(a, b) == 1) { _rsp.style.display = 'block'; _rsp.style.color = 'red'; _rsp.innerHTML = 'пароли не совпадают!'; return; } } _rsp.innerHTML = ""; _rsp.style.display = 'none'; } } 
  • 2
    How are javascript and wpf connected in general? - Pavel Mayorov

If you meant to compare textBox texts, then it’s not at all difficult:

 private void ConfirmTextBox_TextChanged(object sender, EventArgs e) { if(!ConfirmTextBox.Equals(PasswordTextBox.Text)) { labelResult.ForeColor = Color.Red; labelResult.Text = "Paroli ne sootvetstvuyut.."; } }