Классы Windows Presentation Foundation System.Object DispatcherObject Application DependencyObject NavigationService FrameworkTemplate Visual ContentElement UIElement FrameworkContentElement Style FrameworkElement Page Shape TextBlock ContentControl RangeBase TextBoxBase Frame Slider TextBox Window ProgressBar RichTextBox Grid ItemsControl Menu ContextMenu HeaderedItemsControl MenuItem Button Toolbar TreeViewItem Selector RepeatButton TabControl ToggleButton CheckBox Canvas MenuBase NavigationWindow ButtonBase Panel ToolBarTray Control RadioButton ListBox ListView TreeView ComboBox Маршрутизированные события (routed events) Механизм обработки событий WPF базируется на событиях .NET. Новая концепция - маршрутизация событий ( event routing) – события могут подниматься или спускаться по дереву элементов и вызывать обработчики нескольких слушателей (listeners). Три вида событий: Direct events (прямые события) Возникают в одном элементе и не передаются в другие. Пример – MouseEnter. Bubbling events (поднимающиеся, пузырьковые события ) Начинаются во внутреннем элементе и распространяются во внешние – от дочернего элемента к родительским. Пример – MouseDown. Tunneling events ( туннельные, туннелированные события ) Возникают во внешнем элементе и туннелируются во вложенные элементы – от родительского к дочернему элементу. Пример - PreviewMouseMove. Все туннелируемые события в WPF API имеют префикс “Preview” и обычно имеют соответствующие пузырьковые события. С точки зрения реализации маршрутизируемое событие (routed event) - это событие, которое связано с экземпляром класса RoutedEvent, и обрабатывается системой управления событиями WPF (WPF event system). Статический класс EventManager регистрирует маршрутизируемые события. Логическое и визуальное дерево элементов WPF использует понятия логического и визуального деревьев для определения связей между элементами приложения. Логическое дерево элементов WPF базируется на отношении дочерний-родительский и создается при установке значений для свойств, которые представляют модель содержимого элемента, например, значений свойства Content для элементов Button, свойства Items для ListBox или Children для классов Panel (явно в коде или неявно на основе вложенности элементов в разметке). Свойство Parent класса FrameworkElement доступно только для чтения и возвращает логический родительский элемент для данного элемента: public DependencyObject Parent { get; } Логическое дерево используется при поиске объектного ресурса в словарях ресурсов. Во время выполнения приложения каждый из элементов логического дерева обычно расширяется в более сложное дерево визуальных элементов. Маршруты событий обычно проходят по визуальному дереву и могут обрабатываться элементами управления, которые реализуют композицию на визуальном уровне. Классы LogicalTreeHelper и VisualTreeHelper WPF поддерживает классы LogicalTreeHelper и VisualTreeHelper для прохождения по логическому и визуальному деревьям. Для прохода по логическому дереву приложения в программных сценариях разработчики WPF не рекомендуют использовать класс LogicalTreeHelper, так как структура логического дерева доступна через API-интерфейсы коллекций элементов управления. Визуальное дерево может использоваться в приложениях, контролирующих процесс рисования на нижнем уровне с целью оптимизации. В этих случаях удобен класс VisualTreeHelper. В классе LogicalTreeHelper определены статические методы для прохождения по логическому дереву ( методы-оболочки для вызова свойств из классов FrameworkElement и FrameworkContentElement ) : public static DependencyObject GetParent( DependencyObject current ); public static IEnumerable GetChildren( DependencyObject current ); Класс VisualTreeHelper содержит статические методы для прохождения по визуальному дереву : public static DependencyObject GetParent( DependencyObject reference ) ; public static int GetChildrenCount( DependencyObject reference ); public static DependencyObject GetChild( DependencyObject reference, int childIndex ); TreeView TreeView - элемент управления для отображения иерархических данных в виде дерева с элементами, которые можно разворачивать и сворачивать. Класс TreeView наследует ItemsControl. Содержит коллекцию элементов, которая доступна через свойство Items. public ItemCollection Items { get; } Элементами коллекции в TreeView являются обекты TreeViewItem. Класс TreeViewItem наследует HeaderedItemsControl. Каждый элемент TreeViewItem также поддерживает коллекцию элементов, которая доступна через его свойство Items. Свойство Header определяет объект, который выводится в соответствующем узле дерева при отрисовке TreeView. Заголовок может быть строкой или элементом управления UIElement. public Object Header { get; set; } От значения булевского свойства IsExpanded зависит, будет ли ветвь дерева развернута при выводе. Умолчание false. public bool IsExpanded { get; set; } Маршрутизация событий Прямые события ведут себя как обычные события в .NET Framework. Единственный потенциальный обработчик для события - делегат, прикрепленный к событию. При пузырьковой маршрутизации событие распространяется вверх по визуальному дереву от исходного элемента до тех пор, пока не будет обработано или не достигнет корневого элемента. Туннельные события начинаются на корневом элементе и передвигаются вниз по дереву элементов, пока не будут обработаны или не достигнут исходного элемента для события. Маршрутизация не завершается при вызове обработчика события. Чтобы остановить пузырьковый или туннельный процесс, необходимо в обработчике события явно указать, что событие обработано, присвоив свойству Handled значение true. private void MouseDown_Handler (object sender, MouseButtonEventArgs e) { textBlock1.Text += "\n" + sender.ToString(); e.Handled = true; } Класс RoutedEvent Класс RoutedEvent представляет маршрутизируемое событие. В классе определены четыре свойства и один метод. Все свойства доступны только для чтения, свои значения они получают при регистрации события с помощью метода RegisterRoutedEvent класса EventManager. Свойства не могут иметь значение null. public Type HandlerType Тип делегата-обработчика события. { get; } public string Name { get; } Имя маршрутизируемого события должно быть уникальным внутри каждого типа-владельца, глобальной уникальности имени не требуется. public Type OwnerType { get; } Тип – владелец события. Если событие имеет дополнительных владельцев (owners added), свойство возвращает первого объявленного владельца. public RoutingStrategy RoutingStrategy { get; } Значение перечисления System.Windows.RoutingStrategy, которое определяет стратегию маршрутизации события (routing strategy), – Tunnel, Bubble или Direct. public RoutedEvent AddOwner ( Type ownerType ); Добавляет новый класс к владельцам события. Возвращаемое значение используется при определении статического поля, представляющее маршрутизируемое событие в новом классевладельце. Класс EventManager Статический класс EventManager регистрирует маршрутизируемые события и предоставляет информацию о зарегистрированных событиях в системе событий WPF. В классе всего 4 статических метода: • RegisterRoutedEvent для регистрации маршрутизируемого события; • RegisterClassHandler для регистрации обработчика класса - обработчика, который вызывается до вызова экземплярных обработчиков. • GetRoutedEventsForOwner – метод, возвращающий массив маршрутизируемых событий для типа-владельца; • GetRoutedEvents - метод, возвращающий массив всех маршрутизируемых событий, зарегистрированных в системе событий WPF в текущий момент. Метод RegisterRoutedEvent класса EventManager Метод RegisterRoutedEvent регистрирует новое маршрутизируемое событие в системе управления событиями WPF. public static RoutedEvent RegisterRoutedEvent ( string name, RoutingStrategy routingStrategy, Type handlerType, Type ownerType ); При регистрации необходимо указать • имя события (string name); • стратегию маршрутизации (RoutingStrategy routingStrategy); • тип делегата-обработчика (Type handlerType); • тип-владелец (Type ownerType). Перечисление RoutingStrategy, которое определяет стратегию маршрутизации, может принимать значения Tunnel, Bubble, Direct. Параметры не могут иметь значение null. Метод возвращает ссылку на объект типа RoutedEvent, который используется как статическое поле класса и как параметр методов при определении обработчиков событий. Свойства класса RoutedEventArgs Свойства класса RoutedEventArgs доступны в обработчиках маршрутизируемых событий. public RoutedEvent RoutedEvent { get; set; } Значение RoutedEvent, связанное с экземпляром RoutedEventArgs. Значение нельзя изменить в процессе обработки события - будет брошено исключение InvalidOperationException. Значение свойства не может иметь значение null. public Object Source { get; set; } Ссылка на объект, который является источником события. При изменении значения свойства Source свойство OriginalSource сохраняет ссылку на объект, который вызвал метод RaiseEvent. public bool Handled { get; set; } Состояние события. Значение по умолчанию равно false. Значение true указывает, что событие уже было обработано в процессе маршрутизации. Когда свойство получает значение true, событие продолжает движение по маршруту обработки, но будут вызваны только те обработчики, у которых значение свойства HandledEventsToo равно true. public Object OriginalSource { get; } Первоначальный источник события, установленный до любого возможного изменения в процессе обработки.