Страницы

Поиск по вопросам

среда, 13 марта 2019 г.

Простой WPF Binding. Будет ли утечка памяти?

Уважаемые гуру, прошу растолковать по привязкам. В учебных статьях "для чайников" вопросы утечек вообще не рассматриваются, а самостоятельный поиск информации по частям привел к тому, что я запутался. Что я нарыл: Для борьбы с утечками памяти в 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.

Комментариев нет:

Отправить комментарий