СДЕЛАЙТЕ СВОИ УРОКИ ЕЩЁ ЭФФЕКТИВНЕЕ, А ЖИЗНЬ СВОБОДНЕЕ

Благодаря готовым учебным материалам для работы в классе и дистанционно

Скидки до 50 % на комплекты
только до

Готовые ключевые этапы урока всегда будут у вас под рукой

Организационный момент

Проверка знаний

Объяснение материала

Закрепление изученного

Итоги урока

Работа с данными

Категория: Информатика

Нажмите, чтобы узнать подробности

Просмотр содержимого документа
«Работа с данными»

Работа с данными

Работа с данными

Привязка данных и контекст данных Большую роль при работе с данными играет механизм привязки. Для создания привязки применяется элемент  Binding   и его свойства: ElementName : имя элемента, к которому идет привязка. Если мы говорим о привязке данных, то данное свойство задействуется редко за исключением тех случаев, когда данные определены в виде свойства в определенном элементе управления Path : ссылка на свойство объекта, к которому идет привязка Source : ссылка на источник данных, который не является элементом управления

Привязка данных и контекст данных

  • Большую роль при работе с данными играет механизм привязки.
  • Для создания привязки применяется элемент  Binding   и его свойства:
  • ElementName : имя элемента, к которому идет привязка. Если мы говорим о привязке данных, то данное свойство задействуется редко за исключением тех случаев, когда данные определены в виде свойства в определенном элементе управления
  • Path : ссылка на свойство объекта, к которому идет привязка
  • Source : ссылка на источник данных, который не является элементом управления

Свойства элемента Binding помогают установить источник привязки. Для установки источника или контекста данных в элементах управления WPF предусмотрено свойство  DataContext . Рассмотрим на примерах их использование.
  • Свойства элемента Binding помогают установить источник привязки. Для установки источника или контекста данных в элементах управления WPF предусмотрено свойство  DataContext . Рассмотрим на примерах их использование.

Пусть у нас в проекте определен следующий класс Phone: Это сложный класс, который включает кроме простых данных типа string и decimal также и сложный объект Company.
  • Пусть у нас в проекте определен следующий класс Phone:
  • Это сложный класс, который включает кроме простых данных типа string и decimal также и сложный объект Company.

Определим в классе окна MainWindow свойство, которое будет представлять объект Phone:
  • Определим в классе окна MainWindow свойство, которое будет представлять объект Phone:

Здесь установлено свойство DataContext класса MainWindow, после чего мы сможем получить значения из MyPhone в любом элементе в пределах MainWindow:

Здесь установлено свойство DataContext класса MainWindow,

после чего мы сможем получить значения из MyPhone в любом

элементе в пределах MainWindow:

Причем контекст данных переходит от корневых элементов к вложенным вниз по логическому дереву. Так, мы установили в качестве контекста для всего окна объект MyPhone. Однако элементы внутри окна могут конкретизировать контекст, взять какую-то его часть:
  • Причем контекст данных переходит от корневых элементов к вложенным вниз по логическому дереву. Так, мы установили в качестве контекста для всего окна объект MyPhone. Однако элементы внутри окна могут конкретизировать контекст, взять какую-то его часть:

Данный текстовый блок устанавливает в качестве контекста объект Company из общего контекста MyPhone:
  • Данный текстовый блок устанавливает в качестве контекста объект Company из общего контекста MyPhone:

В тоже время нам необязательно конкретизировать контекст для текстового блока, вместо этого мы могли бы с помощью нотации точки обратиться к вложенным свойствам:
  • В тоже время нам необязательно конкретизировать контекст для текстового блока, вместо этого мы могли бы с помощью нотации точки обратиться к вложенным свойствам:

При этом надо учитывать, что когда мы определяем простое свойство объекта в коде c#, то установить в качестве контекста данных мы можем его только там же в коде C#, как, например, выше контекст данных устанавливается в конструкторе окна. Однако если мы вместо простого свойства определим свойство зависимостей, тогда мы сможем устанавливать контекст данных и в коде xaml:
  • При этом надо учитывать, что когда мы определяем простое свойство объекта в коде c#, то установить в качестве контекста данных мы можем его только там же в коде C#, как, например, выше контекст данных устанавливается в конструкторе окна. Однако если мы вместо простого свойства определим свойство зависимостей, тогда мы сможем устанавливать контекст данных и в коде xaml:

В данном случае контекст данных уже не устанавливается, а вместо обычного свойства определено свойство зависимостей. Тогда в коде xaml мы можем обратиться к этому свойству следующим образом:
  • В данном случае контекст данных уже не устанавливается, а вместо обычного свойства определено свойство зависимостей. Тогда в коде xaml мы можем обратиться к этому свойству следующим образом:

Подключение к ресурсам

Подключение к ресурсам

Работа с коллекциями данных. ObservableCollection приложения оперируют не одиночными данными, а большими наборами, коллекциями объектов. Для работы непосредственно с наборами данных в WPF определены различные элементы управления списками, такие как ListBox, ListView, DataGrid, TreeView, ComboBox.

Работа с коллекциями данных. ObservableCollection

  • приложения оперируют не одиночными данными, а большими наборами, коллекциями объектов. Для работы непосредственно с наборами данных в WPF определены различные элементы управления списками, такие как ListBox, ListView, DataGrid, TreeView, ComboBox.

Их отличительной особенностью является то, что они наследуются от базового класса  ItemsControl  и поэтому наследуют ряд общей функциональности для работы с данными. Прежде всего можно выделить свойства: Items : устанавливает набор объектов внутри элемента ItemsSource : ссылка на источник данных ItemStringFormat : формат, который будет использоваться для форматирования строк, например, при переводе в строку числовых значений ItemContainerStyle : стиль, который устанавливается для контейнера каждого элемента (например, для ListBoxItem или ComboBoxItem) ItemTemplate : представляет шаблон данных, который используется для отображения элементов ItemsPanel : панель, которая используется для отображения данных. Как правило, применяется VirtualizingStackPanel DisplayMemberPath : свойство, которое будет использоваться для отображения в списке каждого объекта
  • Их отличительной особенностью является то, что они наследуются от базового класса  ItemsControl  и поэтому наследуют ряд общей функциональности для работы с данными. Прежде всего можно выделить свойства:
  • Items : устанавливает набор объектов внутри элемента
  • ItemsSource : ссылка на источник данных
  • ItemStringFormat : формат, который будет использоваться для форматирования строк, например, при переводе в строку числовых значений
  • ItemContainerStyle : стиль, который устанавливается для контейнера каждого элемента (например, для ListBoxItem или ComboBoxItem)
  • ItemTemplate : представляет шаблон данных, который используется для отображения элементов
  • ItemsPanel : панель, которая используется для отображения данных. Как правило, применяется VirtualizingStackPanel
  • DisplayMemberPath : свойство, которое будет использоваться для отображения в списке каждого объекта

При работе с элементами управления списками важно понимать, что эти элементы предназначены прежде всего для отображения данных, а не для хранения. В каких-то ситуациях мы, конечно, можем определять небольшие списки непосредственно внутри элемента. Например:
  • При работе с элементами управления списками важно понимать, что эти элементы предназначены прежде всего для отображения данных, а не для хранения. В каких-то ситуациях мы, конечно, можем определять небольшие списки непосредственно внутри элемента. Например:

ObservableCollection В примере выше в качестве источника данных использовался список List. Также в качестве источника мы бы могли использовать другой какой-нибудь тип набора данных - массив, объект HashSet и т.д. Но нередко в качестве источника применяется класс  ObservableCollection , который находится в пространстве имен  System.Collections.ObjectModel . Его преимущество заключается в том, что при любом изменении ObservableCollection может уведомлять элементы, которые применяют привязку, в результате чего обновляется не только сам объект ObservableCollection, но и привязанные к нему элементы интерфейса.

ObservableCollection

  • В примере выше в качестве источника данных использовался список List. Также в качестве источника мы бы могли использовать другой какой-нибудь тип набора данных - массив, объект HashSet и т.д. Но нередко в качестве источника применяется класс  ObservableCollection , который находится в пространстве имен  System.Collections.ObjectModel . Его преимущество заключается в том, что при любом изменении ObservableCollection может уведомлять элементы, которые применяют привязку, в результате чего обновляется не только сам объект ObservableCollection, но и привязанные к нему элементы интерфейса.

ItemTemplate и DataTemplate Все элементы управления списками имеют свойство  ItemTemplate , которое позволяет задать свой шаблон отображения данных. В качестве значения оно принимает объект  DataTemplate . В качестве самих данных, которые отображаются в DataTemplate, как правило, выступают объекты пользовательских классов, создаваемых самим разработчиком. Сам шаблон данных представляет разметку xaml, которая управляет визуализацией элемента.

ItemTemplate и DataTemplate

  • Все элементы управления списками имеют свойство  ItemTemplate , которое позволяет задать свой шаблон отображения данных. В качестве значения оно принимает объект  DataTemplate . В качестве самих данных, которые отображаются в DataTemplate, как правило, выступают объекты пользовательских классов, создаваемых самим разработчиком. Сам шаблон данных представляет разметку xaml, которая управляет визуализацией элемента.

Триггеры данных С помощью триггеров данных (data triggers) можно задать дополнительную логику визуализации, которая срабатывает, если свойство привязанного объекта принимает то или иное значение. Например, в случае с примером выше, допустим, мы хотим, если у отображаемого телефона свойство Company равно Microsoft, то этот элемент выделяется жирным или выделяется красным цветом. И для этого добавим в шаблон данных DataTemplate триггер данных:

Триггеры данных

  • С помощью триггеров данных (data triggers) можно задать дополнительную логику визуализации, которая срабатывает, если свойство привязанного объекта принимает то или иное значение. Например, в случае с примером выше, допустим, мы хотим, если у отображаемого телефона свойство Company равно Microsoft, то этот элемент выделяется жирным или выделяется красным цветом. И для этого добавим в шаблон данных DataTemplate триггер данных:

ItemsPanel. Установка панели элементов В примере из прошлой темы про шаблоны данных DataTemplate была одна проблема - по умолчанию ListBox размещает все элементы в один вертикальный столбик, поэтому если мы, к примеру, раздвинем окно приложения по ширине, то у нас появится много незаполненного пространства справа:

ItemsPanel. Установка панели элементов

  • В примере из прошлой темы про шаблоны данных DataTemplate была одна проблема - по умолчанию ListBox размещает все элементы в один вертикальный столбик, поэтому если мы, к примеру, раздвинем окно приложения по ширине, то у нас появится много незаполненного пространства справа:

Такой дизайн сложно назвать удачным. Ведь гораздо удобнее было бы в данном случае, если бы элементы при растяжении по ширине автоматически заполняли новое пространство. Дело в том, что такие элементы как ListBox и ListView по умолчанию инкапсулируют все элементы списка в специальную панель VirtualizingStackPanel, которая располагает все элементы по вертикали. Но с помощью свойства  ItemsPanel  можно переопределить панель элементов в внутри списка. Например, в ситуации выше было бы более эффективно использовать панель WrapPanel:
  • Такой дизайн сложно назвать удачным. Ведь гораздо удобнее было бы в данном случае, если бы элементы при растяжении по ширине автоматически заполняли новое пространство.
  • Дело в том, что такие элементы как ListBox и ListView по умолчанию инкапсулируют все элементы списка в специальную панель VirtualizingStackPanel, которая располагает все элементы по вертикали. Но с помощью свойства  ItemsPanel  можно переопределить панель элементов в внутри списка.
  • Например, в ситуации выше было бы более эффективно использовать панель WrapPanel:

Виртуализация Данные, которыми оперирует программа, могут насчитывать сотни и даже тысячи объектов. Возможно, нам потребуется все эти объекты выводить в списочные элементы - ListBox, ListView, DataGrid. Однако если мы разом загрузим все тысячи объектов в эти элементы управления, то можем столкнуться с проблемой падения производительности. И в этом случае нам надо будет воспользоваться механизмом виртуализации.

Виртуализация

  • Данные, которыми оперирует программа, могут насчитывать сотни и даже тысячи объектов. Возможно, нам потребуется все эти объекты выводить в списочные элементы - ListBox, ListView, DataGrid. Однако если мы разом загрузим все тысячи объектов в эти элементы управления, то можем столкнуться с проблемой падения производительности. И в этом случае нам надо будет воспользоваться механизмом виртуализации.

Виртуализация  позволяет создавать элементу управления контейнер только для непосредственно отображаемых объектов списка. Только для них выделяется память, при этом элемент хранит схему структуры данных, чтобы при прокрутке или изменении видимых объектов соответственно изменить содержимое контейнера. То есть, если в ListView загружено 10000 объектов, однако в реальности элемент отображает только 10 объектов, то ListView создает только 10 объектов ListViewItem. Остальные объекты существуют для ListView только потенциально, в реальности они начинают использоваться только тогда, когда попадают в область видимости по мере прокрутки. В итоге приложение использует меньше памяти, работает быстрее, что повышает производительность.
  • Виртуализация  позволяет создавать элементу управления контейнер только для непосредственно отображаемых объектов списка. Только для них выделяется память, при этом элемент хранит схему структуры данных, чтобы при прокрутке или изменении видимых объектов соответственно изменить содержимое контейнера. То есть, если в ListView загружено 10000 объектов, однако в реальности элемент отображает только 10 объектов, то ListView создает только 10 объектов ListViewItem. Остальные объекты существуют для ListView только потенциально, в реальности они начинают использоваться только тогда, когда попадают в область видимости по мере прокрутки. В итоге приложение использует меньше памяти, работает быстрее, что повышает производительность.

Однако при наличии некоторых условий виртуализация отключается: если контейнеры элементов добавляются напрямую к элементу управления ItemsControl. Например, если объекты ListBoxItem добавляются к ListBox, то ListBox не будет виртуализировать эти ListBoxItem если объект ItemsControl содержит контейнеры элементов различных типов. Например, объект Menu, может содержать объекты типа Separator и MenuItem если для прикрепленного свойства VirtualizingStackPanel.IsVirtualizing установлено значение false если для прикрепленного свойства ScrollViewer.CanContentScroll установлено значение false
  • Однако при наличии некоторых условий виртуализация отключается:
  • если контейнеры элементов добавляются напрямую к элементу управления ItemsControl. Например, если объекты ListBoxItem добавляются к ListBox, то ListBox не будет виртуализировать эти ListBoxItem
  • если объект ItemsControl содержит контейнеры элементов различных типов. Например, объект Menu, может содержать объекты типа Separator и MenuItem
  • если для прикрепленного свойства VirtualizingStackPanel.IsVirtualizing установлено значение false
  • если для прикрепленного свойства ScrollViewer.CanContentScroll установлено значение false

Повторное использование контейнера

Повторное использование контейнера

Кэширование Для большей оптимизации производительности VirtualizingStackPanel производит кэширование объектов. С помощью свойств  CacheLength  и  CacheLengthUnit  класса VirtualizingStackPanel мы можем настроить кэширование видимых объектов в списках. CacheLengthUnit позволяет указать тип кэша - это может быть отдельные объекты списка, страницы списка (страницы представляет набор объектов, одновременно отображаемых в списке) и пиксели (используется преимущественно для изображений). Свойство CacheLength устанавливает количество единиц (объектов, страниц или пикселей), которые будут кэшироваться вирутальной панелью.

Кэширование

  • Для большей оптимизации производительности VirtualizingStackPanel производит кэширование объектов. С помощью свойств  CacheLength  и  CacheLengthUnit  класса VirtualizingStackPanel мы можем настроить кэширование видимых объектов в списках.
  • CacheLengthUnit позволяет указать тип кэша - это может быть отдельные объекты списка, страницы списка (страницы представляет набор объектов, одновременно отображаемых в списке) и пиксели (используется преимущественно для изображений).
  • Свойство CacheLength устанавливает количество единиц (объектов, страниц или пикселей), которые будут кэшироваться вирутальной панелью.

Отложенная прокрутка

Отложенная прокрутка

Провайдеры данных. ObjectDataProvider Для упрощения работы с источниками данных в WPF есть такая функциональность, как  провайдеры данных . Они позволяют связывать источники данных и элементы интерфейса. По умолчанию доступно два провайдера данных: ObjectDataProvider (для работы с объектами) и XmlDataProvider (для работы с данными из xml-файлов). ObjectDataProvider  позволяет использовать в качестве базы данных какой-нибудь локальный объект. Для установки подключения к объекту провайдер применяет следующие свойства: ObjectType : указывает на тип объекта, который будет выполнять роль источника MethodName : указывает на метод объекта из свойства ObjectType ObjectInstance : непосредственно сам объект-источник. В приложение можно одновременно использовать только одно из свойств: ObjectType, либо ObjectInstance IsAsynchronous : при значении true получает данные от источника в асинхронном режиме

Провайдеры данных. ObjectDataProvider

  • Для упрощения работы с источниками данных в WPF есть такая функциональность, как  провайдеры данных . Они позволяют связывать источники данных и элементы интерфейса. По умолчанию доступно два провайдера данных: ObjectDataProvider (для работы с объектами) и XmlDataProvider (для работы с данными из xml-файлов).
  • ObjectDataProvider  позволяет использовать в качестве базы данных какой-нибудь локальный объект. Для установки подключения к объекту провайдер применяет следующие свойства:
  • ObjectType : указывает на тип объекта, который будет выполнять роль источника
  • MethodName : указывает на метод объекта из свойства ObjectType
  • ObjectInstance : непосредственно сам объект-источник. В приложение можно одновременно использовать только одно из свойств: ObjectType, либо ObjectInstance
  • IsAsynchronous : при значении true получает данные от источника в асинхронном режиме

К примеру, определим в файле кода класс, который представляет модель данных, и класс, который будет поставлять данные:

К примеру, определим в файле кода класс, который представляет модель данных, и класс, который будет поставлять данные:

XmlDataProvider XmlDataProvider используется для подключения к xml-документам. Причем xml-документом в данном случае может быть и локальный xml-файл, и xml из интернета. Для организации связи с источником данных XmlDataProvider использует следующие свойства: Source : устанавливает источник данных XPath : задает путь внутри документа xml к целевому набору данных Document : устанавливает ссылку на xml-документ IsAsynchronous : при значении true загружает данные асинхронно

XmlDataProvider

  • XmlDataProvider используется для подключения к xml-документам. Причем xml-документом в данном случае может быть и локальный xml-файл, и xml из интернета. Для организации связи с источником данных XmlDataProvider использует следующие свойства:
  • Source : устанавливает источник данных
  • XPath : задает путь внутри документа xml к целевому набору данных
  • Document : устанавливает ссылку на xml-документ
  • IsAsynchronous : при значении true загружает данные асинхронно

Иерархические данные и HierarchicalDataTemplate В отличие от простых списковых элементов типа ListBox или ComboBox, элементы TreeView и Menu способны отображать иерархические данные, построенные по образу дерева. Как у дерева могут быть ветви, у которых, в свою очередь, также могут быть ветви, так и у TreeView могут быть узлы высшего уровня, которые могут содержать подузлы, а в подузлах также могут храниться подузлы. Для работы именно с иерархическими данными в WPF имеется специальный тип шаблонов данных -  HierarchicalDataTemplate . Этот шаблон задает формат отображения уровня данных. Рассмотрим на примере.

Иерархические данные и HierarchicalDataTemplate

  • В отличие от простых списковых элементов типа ListBox или ComboBox, элементы TreeView и Menu способны отображать иерархические данные, построенные по образу дерева. Как у дерева могут быть ветви, у которых, в свою очередь, также могут быть ветви, так и у TreeView могут быть узлы высшего уровня, которые могут содержать подузлы, а в подузлах также могут храниться подузлы.
  • Для работы именно с иерархическими данными в WPF имеется специальный тип шаблонов данных -  HierarchicalDataTemplate . Этот шаблон задает формат отображения уровня данных. Рассмотрим на примере.

Получение данных из xml Для представления иерархических данных очень удобен формат xml. И в WPF мы можем легко связать данные из xml с иерархическим элементом - TreeView или Menu. Допусти, у нас есть в проекте следующий файл  nodes.xml :

Получение данных из xml

  • Для представления иерархических данных очень удобен формат xml. И в WPF мы можем легко связать данные из xml с иерархическим элементом - TreeView или Menu. Допусти, у нас есть в проекте следующий файл  nodes.xml :

Валидация данных При работе с данными важную роль играет валидация данных. Прежде чем использовать полученные от пользователя данные, нам надо убедиться, что они введены правильно и представляют корректные значения. Один из встроенных способов проверки введенных данных в WPF представлен классом  ExceptionValidationRule . Этот класс обозначает введенные данные как некорректные, если в процессе ввода возникает какое-либо исключение, например, исключение преобразования типов.

Валидация данных

  • При работе с данными важную роль играет валидация данных. Прежде чем использовать полученные от пользователя данные, нам надо убедиться, что они введены правильно и представляют корректные значения. Один из встроенных способов проверки введенных данных в WPF представлен классом  ExceptionValidationRule . Этот класс обозначает введенные данные как некорректные, если в процессе ввода возникает какое-либо исключение, например, исключение преобразования типов.

Теперь установим привязку в xaml-коде:

Теперь установим привязку в xaml-коде:

Настройка внешнего вида при ошибке валидации

Настройка внешнего вида при ошибке валидации

Обработка событий валидации

Обработка событий валидации