•October 31, 2008 • Leave a Comment


In a WPF user interface, you can change the z-order of elements to control overlapping behavior. A hosted Windows Forms control is drawn in a separate HWND, so it is always drawn on top of WPF elements.

A hosted Windows Forms control is also drawn on top of any Adorner elements.

Refrence : http://msdn2.microsoft.com/en-us/library/ms744952.aspx



Relations between Adorner, AdornerLayer and AdornerDecorator

•October 19, 2008 • 2 Comments

I read this article about Adorner. I’d like to make a note to make some concepts more straightforward.

This is a base Adorner from which you will need to subclass.

The AdornerLayer can be considered as a plane in which the Adorners are drawn. Adorners are rendered in an AdornerLayer, which is a rendering surface that is always on top of the adorned element or a collection of adorned elements. Anything placed in the adorner layer is rendered on top of the rest visual elements. In other words, adorners are always visually on top and cannot be overridden using z-order.

Defines the location of an AdornerLayer in visual tree . Window class already has it in the visual tree. It adds the default adorner layer above all other controls in the window.

The workflow is actually quite simple.

AdornerDecorator generates AdornerLayer at where it is in the visual tree. An AdornerDecorator can contain only one child, which is the parent element for the visual tree below the AdornerDecorator. AdornerDecorator divides a visual tree in two parallel branches one of which is the child of the AdornerDecorator with it’s visual subtree, and the other one is AdornerLayer, like the figure below.

Adorning a Single UIElement

To bind an adorner to a particular UIElement, follow these steps:

  • Call the static method GetAdornerLayer of the AdornerLayer class to get an AdornerLayer object for the UIElement to be adorned. GetAdornerLayer walks up the visual tree, starting at the specified UIElement, and returns the first adorner layer it found. (If no adorner layers are found, the method returns null.)
  • Create new instance of the adorner you need and pass it the instance of the UIElement you need to adorn.
  • Call the Add method of the AdornerLayer, and pass it your newly created adorner to bind it to the target UIElement.

The following example binds  SomeAdorner (our own Adorner) to a TextBox named myTextBox.

myAdornerLayer = AdornerLayer.GetAdornerLayer(myTextBox);
myAdornerLayer.Add(new SomeAdorner(myTextBox));

Adorning the Children of a Panel

To bind an adorner to the children of a Panel, follow these steps:

1. Call the static method GetAdornerLayer to find an adorner layer for the element children of which are to be adorned.
2. Enumerate the children of the parent element and call the Add method to bind an adorner to each child element.

The following example binds a SomeAdorner (our own Adorne) to the children of a StackPanel named myStackPanel.

foreach (UIElement toAdorn in myStackPanel.Children)
myAdornerLayer.Add(new SomeAdorner(toAdorn));

Another thing worth of reminding is Validation.ErrorTemplate is rendered on AdornerLayer. So if you want your error template displayed, do not forget to give it a AdornerLayer, like what Karl does, or what Pavan does if you want your DnD works.

To quickly pick up Adorner, this article is probably a good start.

Update: although you can put an AdornerDecorator in XAML to let WPF itself create the AdornerLayer, you can also write code to do the job.

AdornerDecorator decorator = new AdornerDecorator();

decorator.Child = panel;

this.Content = decorator;

AdornerLayer layer = AdornerLayer.GetAdornerLayer(panel);

ControlTemplate and DataTemplate

•October 13, 2008 • 1 Comment

Sometimes it seems that some elements can be placed in the ControlTemplate, and also can be placed in the DataTemplate. This causes great confustion for WPF beginners. But actually there is a clear line between the both, and it is not that some elements can be placed in either of them.

ControlTemplate reflects the behaviors and appearance of a control. It should not have knowledge of the content(data), if it has, because the data is wrapped and represented by ContentPresenter/ItemsPresenter in the ControlTemplate.

DataTemplate is the representation of the data. Similarly, DataTemplate should not have knowledge of its residing control, because DataTemplate only represents the data, and can be placed in any ContentControl.

Karl said :”When authoring your control, attempt to design a control that derives its behavior and appearance from its own dependency properties.” This means that dependencyproperty is designed for its control’s behaviors and apperance, NOT for its content(data)’s behaviors and apperance. All the dependencyproperty-related behaviors and appearance should be defined in the ControlTemplate, whereas all the data-related behaviors and appearance should be defined in the DataTemplate. Note: By Data here I mean Content’s data.

This actually makes up a rule for the default ControlTemplate of the custom control:
When working on the default ControlTemplate for the custom control, do NOT involve DataTemplate,
because you do not know what the content(data) will be and how it will be represented. The content(data) is just abstracted as ContentPresenter/ItemsPresenter in the ControlTemplate.

Tips: How to use SnapsToDevicePixels when creating a ControlTemplate

•October 11, 2008 • 1 Comment

After investigating the default control templates shipped by WPF, I conclude rules of thumb for creating the custom CoontrolTemplate. (The rules don’t necessarily apply on every single default control template of WPF, but I can say they work for most of them.)

1. use Border or Chrome as the outermost level of the custom control template, and set the Border/Chrome’s SnapsToDevicePixels to true

2. if the custom control template is supposed to contain ContentPresenter, ItemsPresenter or ScrollViewer, set the ContentPresenter/ItemsPresenter/ScrollViewer’s SnapsToDevicePixels to {TemplateBinding UIElement.SnapsToDevicePixels}. No matter how many levels stay between the outermost level and the ContentPresenter/ItemsPresenter/ScrollViewer, no need to set the SnapsToDevicePixels for them.


1. No need to set SnapsToDevicePixels for custom control templates of Window, Frame and their subclasses. But it is also OK to set it.

2. ContentControl’s control template does not have a top level container working as layout, but only has a ContentPresenter. Anyway you do not need to customize a control template for ContentControl either.

3. Rules above don’t by default apply on ScrollViewer, ReaderPageViewer, FlowDocumentPageViewer, FlowDocumentScrollViewer, FlowDocumentReader, DocumentViewer and their subclasses. It is better to check their default control templates before starting to make the custom ones.


What is SnapsToDevicePixels about?

How to: Find Control/DataTemplate-Generated Elements

•October 8, 2008 • 3 Comments



To find an element within the template after the template has been applied, you can call the FindName method of the Template.

// Finding the grid that is generated by the ControlTemplate of the Button
Grid gridInTemplate = (Grid)myButton1.Template.FindName("grid", myButton1);

PS: for datatemplate, it is a bit tricky, because the datatemplate is actually applied on the contentpresenter. Therefore, you need first find the contentpresenter of the content control and call FindName on the ContentTemplate of the controlpresenter. Reference the second link above.

Attached Properties spreadsheet

•November 15, 2007 • Leave a Comment

Dr.WPF contributed a spreadsheet he compiled by himself. The spreadsheet listed all the current attached properties in WPF framework. It is definitely a good reference!

I uploaded the spreadsheet as well, for backup purpose. Because of the file extension limit, I have to change the extension to .doc. You can just change it back to .xls after you download it.

Download: attachedproperties.doc

A good tutorial about how to write and use attached property

More advanced attached property use: the Ramora pattern

How to retrieve a FrameworkElement in a data template for ListboxItems

•October 17, 2007 • Leave a Comment


Object container = SomeItemsControlInstance.ItemContainerGenerator.ContainerFromItem(item);

The container is the top element, right under the ItemsPanel, for each of the items.

For example, ListBoxItem for ListBox, ContentPresenter for ItemsControl.

Just list some references for now. gonna complete it later.



VisualOperations class is replaced by VisualTreeHelper Class