Базовый класс модели представления для использования с MVVM в WPF
Автор: Педро Сампайо (Pedro Sampaio)
Как я упоминал в предыдущих публикациях (здесь, здесь и здесь), при разработке приложения WPF в конечном итоге используются модели представления. Поэтому, вместо того чтобы продолжать их разработку из вспомогательной области, я публикую три альтернативы для быстрого получения справки.
Простая модель представления
public class ViewModelBase : INotifyPropertyChanged
{
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, args);
}
#endregion
}
Это простейший из всех возможных классов. Он реализует интерфейс INotifyPropertyChanged и предоставляет два защищенных метода для уведомления об изменении конкретного свойства. Один метод принимает строку как параметр, а второй принимает объект PropertyChangedEventArgs. Проблема этого подхода в том, что продолжается создание новых экземпляров PropertyChangedEventArgs, даже при ограниченном числе свойств в классе.
Более интеллектуальная модель представления
public abstract class ViewModelBaseWithArgCache : ViewModelBase
{
private readonly Dictionary<string, PropertyChangedEventArgs> eventArgsCache;
protected ViewModelBaseWithArgCache()
{
eventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();
}
#region Overrides
protected override void OnPropertyChanged(string propertyName)
{
PropertyChangedEventArgs args;
if (!eventArgsCache.ContainsKey(propertyName))
{
args = new PropertyChangedEventArgs(propertyName);
eventArgsCache.Add(propertyName, args);
}
else
{
args = eventArgsCache[propertyName];
}
OnPropertyChanged(args);
}
#endregion
}
Здесь мы переопределяем метод OnPropertyChanged(string propertyName), чтобы предоставить настраиваемую реализацию. Сначала мы инициализируем словарь того, что будем использовать в качестве кэша. Теперь при вызове OnPropertyChanged(string property) мы проверяем, имеется ли экземпляр EventArgs, кэшированный для этого свойства. Если имеется, то возвращаем его. Если нет, то создаем его, добавляем в кэш и затем возвращаем. Мы используем этот экземпляр для вызова защищенного метода OnPropertyChanged(PropertyChangedEventArgs args) класса ViewModelBase.
Объединенная модель представления
public class UnifiedViewModelBase : INotifyPropertyChanged
{
private readonly Dictionary<string, PropertyChangedEventArgs> eventArgsCache;
protected UnifiedViewModelBase()
{
eventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();
}
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventArgs args;
if (!eventArgsCache.TryGetValue(propertyName, out args))
{
args = new PropertyChangedEventArgs(propertyName);
eventArgsCache.Add(propertyName, args);
}
OnPropertyChanged(args);
}
protected void OnPropertyChanged(PropertyChangedEventArgs args)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, args);
}
#endregion
}
Теперь вместо создания двухуровневой иерархии классов мы объединили их вместе в один класс UnifiedViewModelBase. При желании можно изменить имя этого класса, например на ViewModelBase.
Весь код в этой публикации можно загрузить, нажав эту ссылку.
Надеюсь, это будет полезно.