#c# #wpf #dependency-properties
#c# #wpf #зависимость-свойства
Вопрос:
Я создал элемент управления, который имеет свойство, которое вычисляется с использованием нескольких других свойств в качестве входных данных. Когда любое из этих входных свойств изменяется, свойство необходимо обновить. Я уже сделал это возможным, реализовав для них события, связанные с изменением свойств, пометив зависимое свойство как обновленное. Изменение 3 свойств означает обновление 3 свойств.
Проблема, с которой я сталкиваюсь, заключается в том, что при изменении более одного из этих свойств свойство dependency обновляется каждый раз, когда изменяется какое-либо из этих свойств. Однако для вычисления (и / или визуализации) свойства требуется некоторое время. Когда будет изменено более одного свойства, я бы хотел, чтобы оно обновлялось только один раз, после того, как я обновил все свойства.
Цель: элемент управления необходимо обновлять только тогда, когда программа завершит изменение всех свойств.
Что я пробовал:
- Сделайте свойство ленивым, обновляя его только по запросу. (Не работает, WPF все равно запрашивает его);
- Кэшируйте результат вычисления. (Не работает, потому что всегда изменяется 1 ввод, что делает кеш недействительным);
- Создайте метод для одновременной установки нескольких свойств. (Не работает, некоторые свойства наследуются и поступают из другого элемента управления);
- Сделайте элемент управления свернутым, прежде чем манипулировать свойствами. (Не работает, WPF по-прежнему обновляет свойства).
У кого-нибудь есть лучшее решение?
Ответ №1:
Вы можете отложить создание события изменения свойства. Или создайте метод, который остановит распространение этого события (т. Е. StartUpdating
) и другой метод, который будет запускать все события (т. Е. EndUpdating
).
private bool _isUpdating;
private List<string> _properties = ...;
private void RaisePropertyChanged(string propertyName)
{
if(_isUpdating)
{
if(!_properties.Contains(propertyName)) _properties.Add(propertyName);
return;
}
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
void StartUpdating() { _isUpdating = true; }
void EndUpdating()
{
_isUpdating = false;
foreach(var propertyName in _properties) RaisePropertyChanged(propertyName);
}
и в ваших методах
void LongRunningMethodSync()
{
try
{
StartUpdating();
// do something synchronously
}
finally
{
EndUpdating();
}
}
void LongRunningMethodAsync()
{
StartUpdating();
ExecuteMyAsyncTask(done => EndUpdating());
}
Комментарии:
1. Это работает довольно хорошо, но не совсем то, что я искал (я хотел, чтобы поведение было прозрачным для конечного пользователя). В итоге я получил вспомогательный класс, который использует диспетчер с низким приоритетом для планирования уведомлений об обновлении.