Коллекции и интерфейсы в WinRT

52

Обычно при конструировании класса - такого, как NamedColor из предыдущей статьи - я бы определил конструктор экземпляров защищенным или закрытым, потому что создание отдельных объектов NamedColor за пределами класса не имеет смысла. Такое решение хорошо сработает в первом рассмотренном проекте, но не во втором. Во второй программе классу NamedColor необходим открытый конструктор без параметров, потому что экземпляр класса должен создаваться в XAML как ресурс. Этот конкретный экземпляр NamedColor используется только для одной цели: он предоставляет доступ к статическому свойству All в привязке. Во многих программах встречается класс модели представления, который существует только в одном экземпляре (паттерн Singleton) и предоставляет экземплярные свойства конкретных коллекций. Мы определим такой класс позже.

В NamedColor у меня была определенная свобода выбора типа свойства All. Я мог использовать его фактический тип: List<NamedColor>. Также можно было пойти в другую крайность и определить его как object - это не проблема. При задании свойства ItemsSource сам списковый элемент управления проверяет, реализует ли объект, заданный свойству ItemsSource, интерфейс IEnumerable. Это все, что ему необходимо для обращения к объектам коллекции. Именно по этой причине я определил свойство с типом IEnumerable<NamedColor>. Как бы позднее ни изменилась внутренняя реализация класса NamedColor, я знаю, что это свойство всегда реализует IEnumerable, потому что оно должно предоставить подходящий источник коллекции для спискового элемента управления.

Когда вы впервые заглядываете в документацию по коллекциям и интерфейсам, она кажется довольно запутанной. Программисты с опытом .NET узнают интерфейс IEnumerable<T>, определенный в пространстве имен System.Collections.Generic. Однако в некоторых контекстах этот интерфейс упоминается под именем IIterable<T> и определяется в пространстве имен Windows.Foundations.Collections. Это тот же интерфейс, но программисты C# и Visual Basic обращаются к нему по имени IEnumerable, а программисты C++ - по имени IIterable.

Программисты C# и Visual Basic также привыкли работать с двумя основными типами коллекций: List<T> (упорядоченная коллекция объектов типа T) и Dictionary<TKey, TValue> (упорядоченная коллекция уникальных ключей, отличных от null, и соответствующих им значений). Однако программистам C++ эти два основных типа коллекций известны под именами vector и map соответственно. По этой причине в пространство имен Windows.Foundations.Collections включены интерфейсы IVector<T> и IMap<K, V>, а программисты C# и Visual Basic видят их как интерфейсы IList<T> и IDictionary<TKey, TValue>, определенные в пространстве имен System.Collections.Generic.

Вам уже знаком интерфейс INotifyPropertyChanged, определенный в пространстве имен System.ComponentModel. (Программисты C++ используют интерфейс с тем же именем, но определенный в Windows.UI.Xaml.Data.) Если объекты коллекции, заданной свойству ItemsSource, реализуют интерфейс INotifyPropertyChanged, то любые изменения в свойствах этих объектов будут отражены в визуальных элементах, связанных с этими свойствами. Иначе говоря, привязки в DataTemplate могут реагировать на изменения свойств. Вы уже видели, как это происходит, в проекте ClockButton для одного объекта типа Clock. Решение также работает и с коллекциями.

В работе с коллекциями и списковыми элементами управления также используется другой важный интерфейс INotifyCollectionChanged, определенный в System.Collections.Specialized. Он определяет событие CollectionChanged, которое инициируется при изменении самой коллекции - добавлении, удалении или переупорядочении объектов. Если коллекция, задаваемая свойству ItemsSource спискового элемента управления, реализует интерфейс INotifyCollectionChanged, эти изменения будут восприниматься элементом управления, а элементы будут динамически добавляться или исключаться из вывода.

Для программистов C# класс ObservableCollection<T> реализует интерфейс INotifyCollectionChanged. Именно этот класс следует использовать для указанной цели в программировании Windows Runtime.

Пройди тесты
Лучший чат для C# программистов