WPF is built of three layers:
Layer1
|
Managed Layer
|
·
PresentationFramework.dll -: defines the
layout etc
·
PresenationCore.dll : defines the control
·
WindowsBase.dll : defines the events, dispatcher
, dependency properties
|
Layer 2
|
Unmanaged layer
|
·
Milcore.dll : Media Integration Library core ,
manages animation , videos etc
·
WindowsCodecs: manages the vector UI
|
Layer 3
|
Core API
|
·
Direct3D
·
User32
·
GDI
|
What is dispatcher and thread affinity in WPF?
When a windows application is loaded on the screen each
control is handled using a win 32 handler.
Win32 Handle is very important for any Win32 applications.
For every Win32 apps, Kernel maintains a Table which has entries to identify a
memory address. A HANDLE is actually a DWORD (32 bit integer) which maps the
memory address on the table. So if you get a HANDLE, you can easily locate the
memory address it points to. Each object that you have in Windows (like
windows, buttons, mouse pointers, icon, menu, bitmap etc) has entries in the
table and the object is traced using both internally by windows or by programs
using those HANDLEs. Even though it is just an unsigned integer value, you
should not edit the value, otherwise the HANDLE could not be used to point the
object anymore.
WPF
window is made up of two parts.
1.
Window area which is made up of Operating System
Window
2.
Non - Window area which is inside a WPF window
WPF window has only one window handle (HWND) and each other
controls are actually placed as content to the window and does not have any
entry on Kernel table(no HWND) except of course Popup class in WPF. In this
post I will try to cover the basis of HWND (for those of you who don't know)
and later go on with what are the changes of it with WPF environment.
When WPF application starts, it actually creates
two threads automatically. One is Rendering Thread, which is hidden from the
programmer, so you cannot use the rendering thread directly from your program;
while the other is Dispatcher Thread, which actually holds all the UI elements.
So in other words, you might say Dispatcher is actually the UI thread which
ties all the elements created within the WPF application. Conversely, WPF requires
all the UI elements to be tied with Dispatcher thread, this is called Thread Affinity.
Dispatcher is a class that handles thread affinity. It
is actually a prioritized message loop through which all elements are channeled
through. Every UIElement is derived from DispatcherObject which
defines a property called Dispatcher which points to the UI thread.
Thus from any other thread, if you want to invoke or access UI component, you
need to Invoke using Dispatcher thread. DispatcherObject actually
has two chief duties, to check and verify if the thread has access to the
object.
Routed Events:
A routed event is an event that can invoke handlers in
multiple listeners in an element tree , rather than the object who initially
raised the event.
In WPF, a typical example of
control's hierarchy is root level Window object, than Grid object and then the
other controls which are resides on Grid Control.
The concept of Routed Events comes into the picture when we
want to handle an event, that is originated from some other control in the
hierarchy. Say for example if any user clicks the Button control, that
event which is normally a Button_click event, can be raised by The Button, The
Label, The Gird or The Window.
Types
of Routed Events:
·
Direct Events
·
Bubbling Events
·
Tunneling Events
1. Direct Events: Direct Events are very well known to
.NET people who has worked on standard .NET controls. A direct event gets
raised by the control itself. Say for example Button_click event which
got raised by the Button control itself.
2. Bubbling Events: Bubbling events are first
raised by the control and then are raised by the controls in that control's
hierarchy. Taking our Button control example, If Button is clicked, first
it will raise Button_click event, then the Grid event and at last the Window Event.
The below picture will clear all your doubts:
3. Tunneling Events: The Tunneling Events are the
opposite of the bubbling events as they are raised first by the root element in
the hierarchy and then by the child elements. Same as our previous
example, First Window event will get raised, followed by the Grid Event and at
last the Button_click event.
Dependency Objects:
Every WPF control is derived from DependencyObject. DependencyObject is
a class that supportsDependencyProperty, a property system that is newly
built in WPF.
A dependency property essentially means a property in one
class can be used in other class.
For example the properties top and bottom are not defined in
rectangle class but they can be used in rectangle class as
Every object is derived fromDependencyObject and
hence it can associate itself in various inbuilt features of WPF like EventTriggers,PropertyBindings, Animations,
etc.
Every DependencyObject actually
has an Observer or a List and declares 3 methods called ClearValue,SetValue and GetValue which
are used to add/edit/remove those properties. Thus the DependencyPropertywill
only create itself when you use SetValue to store something.
Difference between CLR properties and Dependency Properties
CLR
property Syntax
private int count;
public int Count
{
get
{
return count;
}
set
{
count = value;
}
}
Dependency
property syntax
//Registering Dependency
Property
public static DependencyProperty PageSizeProperty
=
DependencyProperty.RegisterAttached("PageSize",
typeof(int), typeof(AttachedPropertySample),
new PropertyMetadata(25,
new PropertyChangedCallback(OnPageSizePropertyChanged)));
//PageSize property
declaration
public int PageSize
{
get
{
return (int)
GetValue(PageSizeProperty);
}
set
{
SetValue(PageSizeProperty, value);
}
}
Major features of Dependency Properties are
·
Value Resolution
CLR property reads
value directly from private member while dependency property dynamically
resolves value when you call GetValue() method of dependency property. The GetValue and SetValue methods
are inherited fromDependency Object. You can read more about Dependency
Property
here.
·
In Built Change Notification
Dependency provides
change notification when its value has been changed. You can specify Call Back
while registering dependency property so user will get notification. This is
mainly used in Data Binding.
·
Value Inheritance
If you specify
dependency property to top element it will inherited to all child elements
until child element specifically override the property. Dependency property
value is resolved at runtime when you call GetValue() method.
Attached Events
The XAML language also defines a special type of event
called an attached event. An attached event enables you to add a handler
for a particular event to an arbitrary element. The element handling the event
need not define or inherit the attached event, and neither the object
potentially raising the event nor the destination handling instance must define
or otherwise "own" that event as a class member.
The WPF input system uses attached
events extensively. However, nearly all of these attached events are forwarded
through base elements.
Object Hierarchy
There are quite a few objects in any WPF control.
Let's discuss one by one as in the figure. (The abstract class is
marked in ellipse while concrete class in Rectangles)
- ·
DispatcherObject: Mother of all WPF controls
which takes care of UI thread
- ·
DependencyObject: Builds the Observer for
Dependency Properties
- ·
Visual: Links between managed libraries and
milcore
- ·
UIElement: Adds supports for WPF features
like layout, input, events, etc.
- ·
FrameworkElement: Implementation of UIElement
- ·
Shape: Base class of all the Basic Shapes
- ·
Control: The UI elements that interact with the
user. They can be Templated to change look.
- ·
ContentControl: Baseclass of all controls that
have single content
- ·
ItemsControl: Baseclass for all controls that
show a collection
- ·
Panel: Baseclass of all panels which show one or
more controls within it