Я обнаружил, что обычный способ определения моделей представлений не различает изменения пользователя и изменения системы.Например,
public class PersonViewModel : ViewModelBase
{
private string _name;
public string Name
{
get => _name;
set => Set(ref _name, value);
}
}
Здесь уведомление PropertyChanged будет сгенерировано, если пользователь изменит имя в представлении.Но оно также будет поднято, если приложение по какой-либо причине изменит свойство (например, во время инициализации или в качестве ответа на какое-либо событие).
Я могу захотеть ответить по-разному в зависимости от того, сделал ли пользователь изменениеили система внесла изменения.Например, я могу захотеть регистрировать только изменения, сделанные пользователем для целей аудита.
Приходилось ли другим делать это различие, и как вы его реализовали?
На данный момент,лучшее решение, которое я придумала, - это отправить сообщение, когда пользователь вносит изменение, но когда приложение должно внести изменение, оно должно вызвать метод установки:
public class PersonViewModel : ViewModelBase
{
private string _name;
public string Name
{
get => _name;
set
{
if (SetName(value))
MessengerInstance.Send(new SetNameRequest(this));
}
}
public bool SetName(string value) =>
Set(nameof(Name), ref _name, value);
}
В любом случаесобытие PropertyChanged возникает, так что представление обновляется независимо от того, сделал ли пользователь изменение или нет.Когда пользователь вносит изменения, я могу обработать сообщение, отправленное определенным образом (возможно, при выполнении конкретного варианта использования).Когда система вносит изменения, она просто обновляет представление.
Обновление: Я нашел возможное решение здесь .В случае TextBox
ключевая идея состоит в том, чтобы установить NotifyOnSourceUpdated
в True
, что вызывает событие SourceUpdated
, когда TextBox
обновляет привязку.Затем я могу вызвать команду, когда происходит это событие:
<TextBox Text="{Binding Name, NotifyOnSourceUpdated=True}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SourceUpdated">
<i:InvokeCommandAction Command="{Binding SetNameCommand, Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
В моей модели представления я могу обработать команду любым способом, каким захочу.В моем случае я отправляю сообщение, чтобы оно обрабатывалось соответствующим вариантом использования:
public class PersonViewModel : ViewModelBase
{
private string _name;
public string Name
{
get => _name;
set => Set(ref _name, value);
}
public ICommand SetNameCommand => new RelayCommand(() =>
MessengerInstance.Send(new SetNameRequest(this)));
}
Таким образом, установка свойства Name
из кода обновляет представление, но не вызывает команду,Однако если пользователь изменяет свойство Name
с помощью TextBox
, команда вызывается и в конечном итоге обрабатывается (в дополнение к обновлению представления, поскольку было вызвано событие PropertyChanged
).