Уважаемые гуру, прошу растолковать по привязкам. В учебных статьях "для чайников" вопросы утечек вообще не рассматриваются, а самостоятельный поиск информации по частям привел к тому, что я запутался. Что я нарыл:
Для борьбы с утечками памяти в WPF, нужно привязываться к объектам, реализующим INotifyCollectionChanged. Ок, в случае коллекций, все понятно. Привязываемся через ObservableCollection
Но как быть с простыми типами данных?
Допустим у нас простая страничка, на которой есть текстовое поле, куда пользователь вводит свое имя. Для работы с этим именем, привяжем его к полю name
View:
ViewModel:
public string name {get; set;}
...
this.DataContext = this;
this.InitializeComponent();
Согласно этой страницы, для борьбы с утечкой, необходимо или реализовать INotifyPropertyChanged на объекте-источнике, либо сделать свойство DependencyProperty. Но я нигде не могу найти простой пример, как это правильно сделать.
Тут, в последнем абзаце, вообще написано:
Если вы используете .NET Framework 4.5, то у вас не будет утечки
памяти
Так как правильно реализовать привязку данных?
Ответ
В документе, на которые вы ссылаетесь, написано следующее:
This issue occurs if the following conditions are true:
A data-binding path refers to property P of object X
Object X contains a direct reference or an indirect reference to the target of the data-binding operation.
Property P is accessed through a PropertyDescriptor object instead of a DependencyProperty object or a PropertyInfo object.
Из этих условий необычным является второе: «Object X contains a direct reference or an indirect reference to the target of the data-binding operation».
Если вы программируете с использованием MVVM, ваш объект X скорее всего VM-объект, а целевой элемент привязки — View-объект. В нормальной ситуации объекты VM не имеют права знать о View, и таким образом не должны содержать на него прямых или непрямых ссылок.
Значит, проблема может возникнуть только если у вас View-объект ссылается на другой View-объект. Но свойства UI-объектов обычно являются DependencyProperty, поэтому этот случай тоже в подавляющем большинстве случаев не имеет места.
Что нужно делать?
Если вы производите Binding UI-объекта к другому свойству UI-объекта, имеет смысл обратить внимание на то, является ли то, что вы привязываете, DependencyProperty. В подавляющем большинстве случаев это так и будет.
Если всё же оказывается, что вам кровь из носу нужно забиндить свойство одного UI-объекта на другое свойство, которое не является DependencyProperty (например, как в примере из статьи, которую вы привели:
в этом примере memory leak возникает и в VS 2015), вам нужно поменять Binding на OneTime: в этом случае всё равно вы не получаете нотификаций об изменении свойства (т. к. INotifyPropertyChanged не реализовано, и свойство не есть DependencyProperty).
Более прагматичный подход — не парьтесь с каждой привязкой, тестируйте ваше приложение при помощи memory profiler'а, и если обнаружите утечку памяти, описанную в статье, почините её как указано в п. 2.
Комментариев нет:
Отправить комментарий