NOTICE: On March 23, 2012, a new version of AdvTree was released which is not derived from ItemsControl. It was re-written so as not to be locked into the container generation mechanism provided by the framework supporting ItemsControl. With direct control of container generation, we are able to provide a faster, more robust, implementation of virtualization. Additionally, doing so opens the door to more advanced features such as data virtualization, cell virtualization and row and column pinning.

While AdvTree is not derived from ItemsControl, every attempt has been made to make it look and behave like an ItemsControl. The same is true for AdvTreeNode. For instance, the Items and ItemsSource properties function exactly the same. HierarchicalDataTemplate is still understood. Most will be able to plug the new version into their existing application and re-compile without errors. However, with a re-design of this magnitude breaking changes are unavoidable. Our belief is that the few breaking changes which do exist are in areas that are rarely used. That said, we apologize ahead of time to anyone who is affected by a breaking change in this new version of AdvTree. Hopefully, in these cases the path forward will be obvious. It it is not, we promise to drop everything to provide all the support necessary for successfully migrating your application.

If you are familiar with the standard WPF TreeView you are already familiar with the basics of AdvTree. The container type for items is AdvTreeNode, similar to WPF’s TreeNode. It is possible to use a container type that inherits from AdvTreeNode. To do so in a data binding scenario, create a control based on AdvTree and override method GetContainerForItemOverride, returning an item of the desired type.

The minimum requirement for adding an AdvTree to your UI is either a data source from which the nodes will be generated or creating your nodes directly as children of the tree. Property ItemsSource is used to bind to you data source. The data source can be any regular .Net object which has a hierarchical data structure.

AdvTree supports displaying and editing data in columns, like a grid. In fact, the way it works is exactly the same as it is for AdvGrid. A ColumnDefinitionCollection is used to define columns. Unlike AdvGrid, which supports automatic creation of columns from the data, for AdvTree the ColumnDefinitionCollection must be explicitly provided. Cells are represented by AdvTreeCell, a ContentControl. Cells are generated automatically from the node’s data context in conjunction with the applicable collection of ColumnDefinitions. More on this is provided in the body of this article.

A good place to start exploring AdvTree, other than this document, is the AdvTreeSample application which is included in the DotNetBar installation. Here is a screen shot:

AdvTreeSample

Virtualization

AdvTree supports recycling virtualization. When virtualization is active and a node goes out of view, either by scrolling or by making the viewport smaller, the node itself is disconnected or disassociated from the data item for which it is the container. When a container has been disconnected from its data item in this manner it is said to have been “virtualized.” If scrolling, and a new item is coming into view, the container is then connected to the new item and displayed. When a container has been connected to a data item in this manner it is said to have been “recycled.” In the case where there are no disconnected containers to recycle, a new container is instantiated. In this case the container is said to have been “realized.”

Note: This “recycling” of the containers results in significantly better performance than so-called “standard” virtualization, where virtualized containers are left for the garbage collector and new container is instantiated for each item that comes into view. Because of this, we can see no reason to implement standard virtualization in AdvTree. If you have a scenario where standard virtualization would be preferable to recycling, please let us know.

Virtualization offers two performance benefits: faster loading and reduced memory usage.

Virtualization is off by default. To turn it on, set property VirtualizingMode to Recycling.

Notification

The attached routed event ItemContainerManager.ContainerVirtualizing is raised by a container prior to being virtualized. If this event is handled (its Handled property set to true) then the container will not be virtualized.

Similarly, a container will raise the attached routed event ItemContainerManager.ContainerRealized after a new container is instantiated and has been connected to its data item and added to the visual tree. The event ItemContainerManager.ContainerRecycled is raised by a container when it is recycled.

Cell Virtualization

When the tree is set up to display columns, and virtualization is enabled, then by default the cells are virtualized as well a nodes. Cell virtualization works the same as node virtualization, using recycling as columns are horizontally scrolled into and out of view. There may be certain situations where you want node virtualization but don’t want cell virtualization. For this scenario set property SupressCellVirtualization to true.

Selection

By default, the selection unit is the node, even when the tree (or node) is set up to display columns. To make it so cells are selected, set property CellSelect to true.

To make it so an entire column is selected when the user clicks on the column’s header, set ColumnHeaderClickMode = SelectColumn. When a column is selected, the column definition’s IsSelected property is set to true.

Use the SelectionMode property to select between Single, Multiple and Extended selection modes.

  • Single – Only a single item (node, cell or column) can be selected. When an item is selected the previously selected item is unselected.
  • Multiple – More than one item (node, cell or column) can be selected at a time. Clicking on an item causes it to be selected and added to the current collection of selected rows, cells or columns.
  • Extended – More than one item (node, cell or column) can be selected at a time. In this mode, to select multiple items, either the Control key or the Shift key must be pressed while the item is clicked on. If the Control key is pressed the item’s selection status is toggled and it is either added or removed from the collection of selected rows, cells or columns. If the Shift key is pressed, then an entire range is selected, beginning with the first item in the list of currently selected items and ending with the item which received the click.

When selection mode is either Multiple or Extended, then a set of rules is applied to determine if an item is eligible to be added to the current collection of selected items. The multiple selection rule is set via the property AdvTree.MultiSelectRule which is an enumeration (type AdvTreeMultiSelectRule) with the following possible values:

  • AnyNode – The same as having no rules. Any and all nodes or cells can be selected together.
  • SameLevel – All nodes or cells in the collection must be at the same level in the Tree’s hierarchy.
  • SameParent – All nodes in the collection of selected items must have the same parent in the Tree’s hierarchy.
  • SameType – The underlying data item of all nodes or cells in the collection of selected must be of the same Type.
  • SameColumn – All cells in the collection of selected cells must be in the same column. (Does not apply when CellSelect is false or there are no columns displayed.)

AdvTreeMultiSelectRule supports Flags, so more than one rule may be applied at the same time.

The property SelectedItem references the data item of the selected row. When selection mode is multiple or extended, SelectedItems contains the collection of selected rows and SelectedItem will reference the first row selected. The property SelectedCell references the selected cell, or to be more specific, it references an instance of AdvCellSelectionData which has properties RowItem, Definition, and CellContent. When selection mode is multiple or extended, SelectedCells contains the collection of selected cells and SelectedCell will reference the first cell that was selected. Use property SelectedColumns to obtain an enumeration of type ColumnDefinition with all the columns who’s IsSelected property is true.

When the selection changes, the SelectionChanged routed event is raised.

It is important to note that row, cell and column selection are mutually exclusive. That is, when a row or rows are selected, there will not be any cells or columns that are also selected. The same holds true for cells and columns.

Columns

AdvTree can display your data in columns. Columns can be defined at the top level or on Nodes at any level of the hierarchy (or a combination of both.) Columns are defined by the ColumnDefinitions property of either AdvTree or AdvTreeNode. ColumnDefinitions property is Type ColumnDefinitionCollection and, as its name says, it is a collection of ColumnDefinition objects. Each ColumnDefinition in the collection describes the properties of a single column. Here is an example of ColumnDefinitions applied in a Setter of a Style for an instance of AdvTreeNode:

<Setter Property="ColumnDefinitions">
    <Setter.Value>
        <dc:ColumnDefinitionCollection>
            <dc:ColumnDefinition Header="Order ID" BindingMemberPath="Order_ID" CellIsEditable="False" IsLocked="True" />
            <dc:ColumnDefinition Header="Ship To Name" BindingMemberPath="Ship_Name" CellIsEditable="True" />
            <dc:ColumnDefinition Header="Address" BindingMemberPath="Ship_Address" CellIsEditable="True" />
            <dc:ColumnDefinition Header="City" BindingMemberPath="Ship_City" CellIsEditable="True"/>
        </dc:ColumnDefinitionCollection>
    </Setter.Value>
</Setter>

Setting a valid value for ColumnDefinitions causes a ColumnsPresenter control to be added to the Tree or Node. The ColumnsPresenter is responsible for displaying the column’s headers. It does this with ColumnPresenter controls, one for each ColumnDefinition is the collection. Several properties available on ColumnDefinitionCollection are passed through to the ColumnsPresenter control which is created. Likewise each ColumnDefinition passes on values to the ColumnPresenter control created for it. This being the case, it is possible for a single property value to be set in more than one place. To prevent ambiguity, the precedence rule is as follows: If a property value is set on the ColumnsPresenter or ColumnPresenter control itself, either directly or in a Style Setter, then that value will always take precedence. If the value is unset in the control, then the Definition’s value is passed through. The same holds for AdvTreeCell controls, of which one for each column is created, for each Node that is set to display the columns.

Note that while many common properties of the controls ColumnsPresenter, ColumnPresenter and AdvTreeCell can be controlled via the Definition, it is always possible to define a Style for the control when required to modify values that are not exposed by the Definitions.

Basic Column Setup

The minimum requirement for defining Columns is a ColumnDefinitionCollection containing at least one valid ColumnDefinition. A valid ColumnDefinition will, at a minimum, have a value for either BindingMemberPath or Binding. (It will also likely require a value for Header, although technically this is not required as it could be provided in a Style defined for AdvTreeCell.) When a Cell control is created to display the column data for a particular Node, the Cell’s DataContext is inherited from its parent Node. BindingMemberPath is a reference to a property on the object which is set as DataContext. A binding is created for the Cell’s Content property and is given the path specified by BindingMemberPath. For more control over the Binding used to bind Content, the property ColumnDefinition.Binding can be used. When a value for Binding is set, it is applied directly to the Cell’s Content property.

Some of the more common settings available through ColumnDefinitionCollection are:

  • To allow the user to reorder the columns by dragging a column header from one location to another, set ColumnDefinitionCollection.AllowColumnReorder = True. (Default is False.) An individual column can be locked in place by setting its IsLocked property to True.
  • To allow the user to resize columns set AllowColumnResize = true.
  • To show grid lines for all columns, use ColumnDefinitionCollection.ShowGridLines. To change the grid line Brush, use property GridLineBrush.
  • To set a background which covers the entire Column header area, use HeaderBackground.
  • To enable a context menu which allows the user to add or remove columns set IsContextMenuEnabled = True. A default context menu is created and set to the ContextMenu property of the ColumnsPresenter. If a value for ColumnsPresenter.ContextMenu is already set this property is ignored.

Common settings available through ColumnDefinition include:

  • ColumnDefinition.Header sets the Header for the column.
  • To make all cells in the Column editable, set IsCellEditable = true. BeginEditTriggerMode is also available.
  • To prevent a cell from being selectable, set CellIsSelectable = false.
  • To prevent the user from moving the column with a drag operation, set IsLocked = true.
  • Use property StringFormat to format the cell display value  to something other than default. This property is passed along to the Cell’s ContentStringFormat property.
  • To define a style to use for all Cells in the column, use property CellStyle.
  • It is possible to control the Visibility of the column (including header and all cells) with the property ColumnDefinition.Visibility.
  • The  generated Cells’ EditTemplate property can be set via the ColumnDefinition.

Initial column width is set via the Width property of ColumnDefinition. Width is a value of type GridLength. This the same Type used by the standard Grid control’s ColumnDefinition and RowDefinition elements, and is used in the same way. Briefly,

  • To specify automatic sizing, use the value “Auto”. (Auto is the default.)
  • To specify a size relative to the available width, use the star notation, as such: “2*”
  • To specify an absolute width, simply use the numerical value.

Column Sorting

Sorting by column is supported by AdvTree. Columns can be sorted both programmatically and in response to the end user clicking on the column header. To enable end user sorting, set property IsUserSortByColumnsEnable of the ColumnDefinitionCollection to true.

Two options exist for sorting programmatically. One option is via property ColumnSort of ColumnDefinition. ColumnSort is an enumeration of type ColumnSort, with the following possible values: None, Ascending, Descending and Unsortable. Two additional values, SecondaryAscending and SecondaryDescending are used internally and will have no effect if set by the client. (A value of Unsortable will make it so the user is unable to sort by that particular column.) The other way to sort by column programmatically is by calling method SortByColumn(string, ListSortDirection) passing in the name of the property to sort by and the sort direction. Both AdvTree and AdvTreeNode also expose a method SortByColumn. SortByColumn will only work if the object (AdvTree or AdvTreeNode) is the owner of the ColumnDefinitionCollection which contains the definition of the column to sort by.

Column Inheritance

There is a distinction between a Node’s ColumnDefinitions property value and the ColumnDefinitionCollection which is used by the Node to generate and display actual Cells. The former is used by the Node to create the column headings, it is not used by the node for the purpose of displaying data. It is the descendants of the Node on which the ColumnDefinitions are originally set which display the actual Cells. A reference to the ColumnDefinitionCollection which defines a Node’s cells is available via the Node’s CellDefinitions property.

In certain circumstances it is desirable to have some control over how the CellDefinitions property is inherited by a Node. For example, you might wish to define the columns at the level of the Tree root, but in the next level of the hierarchy show a standard Node header without columns. This type of scenario and others like it is possible using the property InheritsColumns. InheritsColumns is an enum of type AdvTreeNodeInheritsColumnsMode. The possible values are IfColumnDataPresent, Always and Never. The default value is IfColumnDataPresent.

When InheritsColumns is set to IfColumnDataPresent a node at any level of the Tree Hierarchy will look to its nearest ancestor which has either a non-null value for its CellDefinitions property or a non-null value for its ColumnDefinitions property (ColumnDefinitions takes precedence.) If the search yields a candidate ColumnDefinitionCollection for the Node’s CellDefinitions, a test is made to ensure that the Node’s DataContext object has in it’s Type description at least one match to a ColumnDefinition’s ValueBindingPath or Binding. A single match is all that is required for the Node to accept the Columns as its own and set up the corresponding Cells. If a match is not found, then the Node will render as if no column definitions are defined.

Setting InheritsColumns to Always will force the Node to accept the first available ColumnDefinitionCollection and generate Cells for, whether or not the required data is present.

A value of Never will cause the node to display itself without columns in all cases.

In Place Editing

In place editing is supported for both Node data and Cell data (when displaying columns.) Property IsEditable of AdvTreeNode controls whether the node’s header can be edited by the user. If displaying columns, then property IsEditable of AdvTreeCell is used. (To set IsEditable on every cell in a column, use the IsCellEditable property of the ColumnDefinition.)

Entering edit mode is controlled with the property BeginEditTriggerMode. The possible values for BeginEditTriggerMode are:

  • Click – Edit mode is entered when the Node or Cell is clicked on.
  • ClickSelected – Edit mode is entered with a click, but only if currently selected.
  • ClickOrKeyDown – Edit mode is entered with a click or by typing when the cell or node has focus.
  • ClickOrKeyDownSelected – Edit mode is entered with a click or by typing only when the node or cell is already selected.
  • DoubleClick – Edit mode is entered with a double click.
  • DoubleClickSelected – Edit mode is entered with a double click if the node or cell is currently selected.
  • DoubleClickOrKeyDown – Edit mode is entered with a double click or by typing.
  • DoubleClickOrKeyDownSelected – Edit mode is entered with a double click or by typing, if the node or cell is already selected.
  • Manual – Edit mode is only entered with a call to BeginEdit().

The user can exit edit mode without committing the value at any time by pressing the escape key. Also, both the AdvTreeNode and AdvTreeCell controls expose a public method EndEdit() with the option of committing the value. (There is also a method BeginEdit() for manually initiating an edit.) If the default editor is in use, the user can commit the current value by pressing the Enter key.

Note: AdvTree uses the same framework for displaying columns and and editing cells as AdvGrid. The AdvGrid Quick Start Guide has a more detailed discussion of editing and how to customize the editor for a particular column. Much of the information about editing also applies to node data.

Drag and Drop

Drag and Drop in AdvTree is fully supported via the DevComponents DragDrop utility described here.

Search

AdvTree supports searching via methods FindNode and ExpandToNode. Both methods have as input parameter either an object which is itself the item to find, or a Predicate used for identifying the desired item. (A Predicate is a .Net construct representing a delegate method that returns a Boolean.) Here is an example of calling FindNode with a Predicate. The predicate in this case is simply specifying that the value of Name on the item should equal the value entered in the search text box.

string name = SearchText.Text;
AdvTreeNoe node = Tree.ExpandToItem<filesystemobjectdata>(f => f.Name == name, AdvTreeNodeSearchMethod.DataTraversal, true);
if(node != null)
    Tree.Focus();

Note that the second parameter to method ExpandToItem is an enumeration of type AdvTreeNodeSearchMethod. Its possible values are DataTraversal and NodeTraversal. These are specifications of the two search methods supported by AdvTree. (For completeness, the third parameter in method ExpandToItem is a Boolean indicating whether the node, if found, should have its IsSelected property set to true.)

The search by Data Traversal method uses reflection to traverse the data object bound to the tree’s ItemsSource property. At each level of the hierarchy, it first checks for a match from within all items returned by enumerating through ItemsSource. If no match is found, it then looks for a public property which can be cast to IEnumerable and if one is found, the search continues recursively into its value. For search by data traversal to work your data must be structured in the described manner. If not, then the item simply cannot be found.

The search by node traversal method does not require the data be structured in any specific manner. However, it is potentially much more costly from a performance perspective with large data sets. In this method, at each level of the hierarchy all nodes are enumerated and first checked for a match. If no match is found, the nodes child nodes are recursively enumerated and their Item values checked in turn. What makes this method potentially costly is that the nodes must be created if they do not exist, which will be the case for the majority of nodes when virtualization is being used but also comes into play when virtualization is not being used because the children of nodes which have never been expanded will not have been created regardless of the virtualizing mode in use.

Customizing Visual Appearance

The visual appearance of AdvTree and its constituent controls can be changed in a number of ways. Of course, the standard WPF practices for customizing controls are fully supported, including support for custom Styles and Templates.

Many of the resources which define the appearance of the tree are specified via resource references. The keys for these resources are ComponentResourceKey objects. As a general rule, the resource key is defined as a static property on the control class which uses it.

Overriding or customizing a resource which is referenced via a ComponentResourceKey is as simple as defining a new resource and giving it the same key value. Most often, the new resource can be defined in Application or Window Resources. Occasionally, it will be necessary to define the key within the resources collection of the Tree itself. (This will be the case, especially, if a non-default value for AdvTree.VisualStyle has been set.)

Here is an example of a resource with a Key that is a ComponentResourceKey. (This resource provides the default value for AdvTree’s Padding property.):

<Thickness x:Key="{x:Static dc:AdvTree.PaddingKey}" Left="3" Top="0" Right="0" Bottom="0" />

The resource keys available for this type of customization are generally discoverable as static properties on the class which uses the resource identified. For convenience, here is a list of the resource keys available:

AdvTree Resource Keys

  • BorderBrushKey
  • BackgroundKey
  • PaddingKey
  • ScrollViewerStyleKey – identifies the Style for the ScrollViewer used in the default AdvTree control template.
  • ColumnHeaderDropAdornerTemplateKey – identifies DataTemplate used for column header drop adorner.
  • ColumnHeaderDragAdornerTemplateKey

AdvTreeNode Resource Keys

  • PaddingKey
  • ForegroundKey
  • VerticalRootLineStrokeKey
  • HorizontalRootLineStrokeKey
  • ContainedSelectionBoxBorderStyleKey – identifies Style to apply to the Border which is the selection box when SelectionBoxType is Contained.
  • ContainedHighlightBoxBorderStyleKey – identifies Style to apply to the Border which is the highlight box when SelectionBoxType is Contained.
  • ContainedSelectionBoxBorderBrushKey
  • ContainedSelectionBoxBackgroudKey
  • ContainedHighlightBoxBorderBrushKey
  • ContainedHighlightBoxBackgroundKey
  • FullSelectionBoxBorderStyleKey – identifies the Style to apply the the selection box (which is a Border) when SelectionBoxType is Full.
  • FullHighlightBoxBorderStyleKey – identifies the Style to apply to the Border which is the highlight box when SelectionBoxType is Full.
  • InactiveSelectionBoxBorderBrushKey – identifies the Brush to use for the Border of the selection box when the Tree does not have focus.
  • InactiveSelectionBoxBackgroundKey
  • PlusMinusExpanderToggleButtonStyleKey – identifies the Style for the ToggleButton which is used as expander when ExpanderButtonStyle is PlusMinus.
  • PlusMinusExpanderToggleButtonBackgroundKey
  • TriangleExpanderToggleButtonStyleKey – identifies the Style for the ToggleButton which is used as expander when ExpanderButtonStyle is Triangle.
  • EditingBorderStyleKey
  • DefaultEditorSelectionBrushKey – identifies the Brush to use as value for TextBox.SelectionBrush in the default editor template.
  • DefaultEditTemplateKey – identifies the default edit template.

AdvTreeCell Resource Keys

  • PaddingKey
  • ForegroundKey
  • SelectionBoxBorderStyleKey
  • SelectionBoxBorderBrushKey
  • SelectionBoxBackgroundKey
  • HighlightBoxBorderStyleKey
  • HighlightBoxBorderBrushKey
  • HighlightBoxBackgroundKey
  • InactiveSelectionBoxBackgroundKey
  • InactiveSelectionBoxBorderBrushKey
  • EditingBorderStyleKey
  • DefaultEditorSelectionBrushKey
  • DefaultEditTemplateKeyj

ColumnsPresenter Resource Keys

  • PaddingKey
  • BorderBrushKey
  • ForegroundKey
  • HeaderBackgroundKey
  • GridLineBrushKey
  • ContextMenuStyleKey – identifies the Style that is applied to the ContextMenu created by default when ColumnsPresenter.IsContextMenuEnabled is true.

Visual Styles

Perhaps the easiest way to modify the appearance of an AdvTree is via its VisualStyle property. There are four built-in visual styles: Windows Explorer emulation, Office 2010 Blue, Office 2010 Silver and Office 2010 Black.

It is worth noting that these visual styles are simply collections of resource re-definitions grouped together into a single ResourceDictionary. When a visual style is applied, the resource dictionary which defines it is merged into the AdvTree’s Resources collection. You can still re-define or override a resource that is included in the style definition by adding the new resource definition to the Tree’s resources collection.

It is easy to define your own visual styles by (re)defining the resources you wish to modify and grouping them into a separate resource dictionary and merging that dictionary into the tree’s resources.

Public Interface

Following are lists of the common events, properties and methods available on AdvTree and AdvTreeNode controls.

AdvTree Interface

AdvTree Events:

SortByColumnRequested – A routed event raised when the user clicks a column header to sort (ColumnHeaderClickBehavior is SortByColumn.) Handle this event to stop default sorting and provide custom sorting.

SelectionChanged – A routed event raised when the selection changes.

ItemsChanged – A routed event raised when the content of the Items collection changes.

AdvTree Methods

BringIntoView – There are five overrides of BringIntoView which can be used to bring into view a specific node and whether to include the node’s children if expanded, bring into view a specific item, a specific index (Note that the index is relative to the flattenned tree) and finally one for bringing into view a specific column.

ClearSelection – Clears current selection.

ContainerFromIndex – Get the node at the specified index. (Index is relative to the flattened tree, where all expanded nodes and their children are included.) Option to create the node if it doesn’t exist (applies when virtualization is enabled.)

ContainerFromItem – Returns the node given an item. Node can be at any level of the hierarchy. Optional parameter to specify whether or not to create the node if it does not exist.

CollapseAll – Collapses expanded nodes, with option to collapse only top level nodes or to collapse nodes at all levels. If the former, when nodes are expanded again, the expanded tree is preserved.

ExpandToLevel – Expands all branches to a specified level of the hierarchy.

ExpandToItem – Searches for a specified item and expands the tree so that the found item is visible. Optionally, a Predicate (delegate with return type of bool) can be used to identify the item.

FindNode – Searches for a specified item and returns the Node which contains it. This method is like ExpandToItem but without expanding any nodes.

IndexFromContainer – Get the index of the node within the flattened hierarchy of the tree.

IndexFromItem – Get the index of the item within the flattened hierarchy of the tree.

IsItemSelected – Use to determine if a particular item is part of the current selection.

GetNodeAt – One override gets the Node which is located at a specific position. The position is relative to the tree control. Another override gets the node which corresponds to a specified index within the tree. The index is a flattened index.

IndexOf – Get the flattened index within the tree of a specific node.

Remove – Removes a node from its parent node and the data item for which it is the container from its parent’s Items collection.

SelectAll – If columns are being displayed, then all columns are selected.

SortByColumn – Causes child nodes to be sorted by the values of a specific column, in a specified direction.

AdvTree properties:

CLR Properties

AllSelected – Will return true if all columns are selected.

ExistingNodes – Returns an enumeration of all realized nodes, at all levels of the hierarchy.

Items – Gets a reference to the underlying ItemsCollection. This is a read-only property.

ItemContainerManager – Gets a reference to the object responsible for container (node) creation and virtualization. This is the counterpart to ItemsControl’s ItemContainerGenerator.

LogicalExtent – This is the number of nodes which are either direct descendents of the tree or are children of expanded nodes.

FirstVisibleNodeIndex – Gets the index of the first visible node (index is flattened, i.e. inclusive of all nodes regardless of hierarchy level.)

LastVisibleNodeIndex – Gets the index of the last visible node in the tree.

ScrollViewer – Gets a reference to the ScrollViewer for the tree, if there is one.

SelectedColumns – An enumeration of the ColumnDefinitions which are currently selected. Column selection is enabled by setting ColumnHeaderClickBehavior to SelectColumn.

SupressCellVirtualization – When VirtualizationMode is Recycling both nodes and cells are subject to virtualization. Set this property to prevent the virtualization of cells.

Dependency Properties

ActiveItem – This is the data item of the node which currently has keyboard focus. Read-only.

AlternationCount – Performs same function as ItemsControl.AlternationCount. Setting to a value greater than 1 will result in the tree’s nodes’ AlternationIndex values alternate between 0 and AlternationCount – 1. This value can be used in a Style trigger to modify properties of the nodes based on their alternation index. An example of this is provided in the sample AdvTreeSample.

CalculateFullExtentOnLoad – When virtualization is enabled and there are nodes which load in the expanded state the true vertical extent of the tree will not, by default, be calculated. That is, the tree will have no way of knowing what nodes are expanded until the user actually scrolls them into view. Set CalculateFullExtentOnLoad to cause the tree to pre-load the entire tree for the purpose of finding out what nodes are expanded so the true extent can be calculated. Use with caution because this can have a dramatic effect on load time performance.

CellSelect – Applies when columns have been defined (see below.) When true, Cells are the selection unit instead of Nodes.

ColumnDefinitions – Defines columns for the Tree. More on columns is provided below.

DoubleClickExpandsNode – When true, double clicking on a node causes it to expand or collapse. The default value is True.

HasItems – Gets whether the Items collection count is greater than 0. Read-only.

HighlightSelectedCellColumnHeader – Determines whether the column headers of selected cells are highlighted.

HorizontalGridLineBrush – Brush for horizontal grid lines when ShowHorizontalGridLines is set.

HorizontalGridLineHeight– Height of the horizontal grid line when ShowHorizontalGridLines is set.

HotTrack – When true, the Node or Cell with mouse over is highlighted.

IsDragDropEnabled – When set, the tree is set up to be both source and target of drag/drop. Is the same as setting both DragDrop.IsDropTarget and DragDrop.IsDragSource to true.

IsSelectionFocusAware – When true, the selection box which highlights a selected item is grayed when the Tree does not contain the input focus.

ItemsSource – An IEnumerable which serves as source for the items which populate the Items collection. This property is equivalent to ItemsControl.ItemsSource.

ItemContainerStyle – Style for the item containers. Note that containers for AdvTree are always instances of AdvTreeNode. A value set here is inherited by child nodes if their ItemContainerStyle property is unset.

ItemContainerStyleSelectorStyleSelector for selecting the Style for the container for a particular item.

ItemTemplate – A DataTemplate which shows how to render the node headers. This value is mapped to child nodes’ HeaderContentTemplate property. A value set here is inherited by child nodes if their ItemTemplate is left unset.

ItemTemplateSelector – A DataTemplatSelector which can be used to specify ItemTemplate based on specific items.

MultiSelectRule – Allows user to define various rules for when items can be selected when the selection mode is either Multiple or Extended. More on this is provided below.

ScrollMode – Determines whether scroll-by-item is enabled and, if so, how the last item is positioned. Possible values are Normal, ByItem and ByItemBottomFlush. Default is Normal.

SelectedCell – When SelectionMode is Single and CellSelect is True, this property will identify the currently selected cell. When multiple selection is enabled, SelectedCell will be set to the first cell selected of the collection of selected cells.

SelectedCells – When SelectionMode is Multiple or Extended and CellSelect is True, this property will return an ObservableCollection containing the currently selected cells.

SelectedItem – Will identify the currently selected item when SelectionMode is Single. When multiple selection is enabled, SelectedItem will be set to the first item selected of the collection of selected items.

SelectedItems – When SelectionMode is Extended or Muliple, will return an ObservableCollection containing references to the currently selected items.

SelectionBoxType – Possible values are None, Full and Contained. When None, Nodes or Cells are not highlighted in any way when selected or when the mouse is over them. Contained means that the selection/highlight box is restricted to the bounds of the node or cell. Full means that the selection/highlight box extends from one edge of the Tree’s viewport to the other. When CellSelect is true, SelectionBoxType of Full does not apply.

SelectionMode – Possible values are Single, Multiple and Extended. More on selection modes is provided below.

ShowHorizontalGridLines – Determines whether horizontal grid lines are shown.

ShowRootLines – Set this property to show the lines which connect parent nodes to child nodes.

VirtualizingMode – Sets the virtualization mode for the tree. Possible values are None and Recycling. Default value is None. More about virtualization is provided below.

VisualStyle – 5 built-in visual styles are included with AdvTree: the default, an emulation of Windows Explorer, and the three color schemes of Office 2010: Blue, Silver and Black. Setting this property is the same as setting a value for the VisualStyleManager.VisualStyle attached property on the tree. (More on customizing appearance is provided below.)

AdvTreeNode Interface

AdvTreeNode Events

BeforeSelected – A bubbling routed event raised before the value of IsSelected changes from false to true. Setting the event argument’s Handled property to true will cancel the selection.

Checked – A bubbling routed event raised when the built-in CheckBox is checked. Property CheckBox must be either TwoState or ThreeState.

Collapsed – A bubbling routed event raised when the node’s IsExpanded property changes from true to false.

Connecting – Routed event raised when the node is being connected to its data item and fitted into the visual tree. This event occurs as part of the virtualization/realization process.

Disconnecting – Routed event raised when a node is in the process of formally disconnecting itself from its data item. Will not be raised if virtualization is not enabled.

Expanded – A bubbling routed event raised when IsExpanded changes from false to true.

IsCellSelectedWithinChanged – Bubbling routed event raised when th value of IsCellSelectedWithin changes.

Selected – A bubbling routed event raised when the value of IsSelected changes from false to true.

Unchecked – A bubbling routed event raised when the built-in CheckBox is un-checked. Property CheckBox must be either TwoState or ThreeState.

Unselected – A bubbling routed event raised when the node’s IsSelected property changes to false.

AdvTreeNode Methods

BeginEdit – Manually puts the node into edit mode.

Collapse – Collapses the node by setting IsExpanded to false and optionally recurring through all descendant nodes collapsing them as well.

EndEdit – Manually ends edit mode with option to commit the edited value.

ExpandToLevel – Recursively expands to a given level within the node’s hierarchy.

GetCell – Use to get an AdvTreeCell contained by the node that corresponds to a specific ColumnDefinition.

GetChildNodes – Use to obtain an enumeration of all of the node’s child nodes. Optionally include all the descendants of the child nodes as well. Option to include nodes which are unrealized.

SortByColumn – Causes the node to sort children by a specified column, in a specified direction.

AdvTreeNode Properties

CLR Properties

CellDefinitions – This is the ColumnDefinitionCollection which defines the columns which present the node’s data (not the node’s children.) By default, a node inherites this value from its parent node. If the parent node has a value for ColumnDefinitions, this becomes the child’s CellDefinitions.

Cells – Gets an enumeration of the AdvTreeCells which are children of the node. If HasCells is false, this property will return an empty enumerable.

HasCells – Gets whether this node has cells defined.

IsEditing – Returns true if the node is currently in edit mode.

IsCellEditingWithin – Returns true if a Cell contained by the node is currently in edit mode.

IsConnected – Returns true if the node is currently connected – that is, it is in a valid state for rendering.

Items – An ItemsCollection which contains and manages the child items of the node.

ParentTree – Gets the parent AdvTree.

ParentNode – Gets the node’s parent node, if it is HierarchyLevel greater than 1.

PreviousSibling – Gets the sibling which comes immediately before the node within the node’s parent.

PreviousNode – Gets the node which comes immediately before the node within the entire tree. For example, if the node is the first node within it’s parent, then it will return its parent node for as value of property PreviousNode.

NextSibling – Gets the node which immediately follows the node, scoped within its parent node. If the node is the last node within its parent, then null is returned.

NextNode – Gets the node which immediately follows the node, scoped within the entire Tree.

Dependency Properties

AlternationCount – performs same function as TreeView.AlternationCount, allowing the alternation to begin with a specific node in the hierarchy.

AlternationIndex – This is a readonly property which is set by the framework when a parent’s AlternationCount is greater than 1. This property can be used in Style trigger to modify appearance of the node.

BeginEditTriggerMode – provides a means for defining what conditions are required for the node to enter Edit mode. (Only applies when IsEditable is true.) More on node and cell editing is provided below.

CanHaveItems – Determines whether the node can have child nodes. If false, then the node’s expander button is removed from the visual tree. True by default.

CanUserCollapse – provides a means to make a node so that it cannot be collapsed (or expanded) by the user interacting with the UI. When set to false, the Expand/Collapse button is not visible. Note that this property has no effect on setting IsExpanded in code.

CellSelect – by default, the value for CellSelect set at the Tree level is inherited by all nodes in the tree. This property provides a means of overriding this behavior for individual nodes.

CheckBox – Enables a CheckBox be displayed for the node. Can be one of three values: None, TwoState or ThreeState.

ColumnDefinitions – Define columns to begin at a specific level in the hierarchy. More on columns is provided below.

EditorSettings – An object which is or derives from class EditorSettings which is used to customize the editor that is used to edit the node’s header.

EditorStyle – A Style applied to the ContentEditingControl which is used to both display and edit the node header.

EditTemplate – Defines the template used for editing the node’s value. More below.

ExpanderButtonStyle – Provides a means of defining a Style to apply to the ToggleButton which is used to expand and collapse the node. By default, this value is null (the expander button style being defined by one of the pre-installed expander button types.)

ExpanderButtonType – Two built-in types are provided: Triangle and PlusMinus. Note that setting a value for ExpanderButtonStyle will override the style provided by this setting.

HasItems – A readonly boolean indicating if the node has children.

Header – The content displayed by the node. If the node is displaying data in columns this property is ignored.

HeaderTemplate – A DataTemplate which shows how to render Header.

HierarchyLevel – This is a read-only property indicating the level of the node in the Tree’s hierarchy. Top level nodes have HierarchyLevel of 1.

HorizontalGridLineBrush – Get or set the Brush used for the horizontal grid line. By default, this property is inherited from the node’s parent node, if it has one, or the parent tree.

HorizontalGridLineHeight – Determines the height of the horizontal grid line. By default, this property is inherited from the node’s parent node, if it has one, or the parent tree.

ImageSource – Defines an ImageSource for an image which to display with the Node’s header. The default value is null.

Indent – Gets or Sets the width between the Node’s left edge and the left edge of the panel which presents the Node’s children. If this value is unset (the default value is NaN) then a value for it is automatically calculated based on the size of the expander button.

InheritsColumns – Sets a value which determines how column data propagates to the node. Three possible values: Always, Never or IfColumnDataPresent. The default is IfColumnDataPresent, which means that, if the node’s data context is an object which has the properties matching the column definitions of the nearest ancestor which defines columns, then the node will display the columns, otherwise the node will display its Header. More on columns is provided below.

IsChecked – Applies when CheckBox is either TwoState or ThreeState. Is bound to the check box’s IsChecked property.

IsCellSelectedWithin – Will be true if one of more cells within the node are selected. Readonly.

IsEditable – When true, the Header property can be edited in place. See more about editing below.

IsSelected – Gets or sets whether or not the node is selected. If IsSelectable is false, this property is ignored.

IsSelectable – Determines whether the node can be selected. The default value is true.

IsExpanded – A boolean which gets or sets whether the node is expanded. Will have effect only if the node’s HasItems property is True.

ItemsSource – An IEnumerable which serves as source for the items which populate the Items collection. This property is equivalent to ItemsControl.ItemsSource.

ItemContainerStyle – Style for the item containers. Note that containers for AdvTreeNode are always instances of AdvTreeNode. A value set here is inherited by child nodes if their ItemContainerStyle property is unset.

ItemContainerStyleSelectorStyleSelector for selecting the Style for the container for a particular item.

ItemTemplate – A DataTemplate which shows how to render the headers of child nodes. This value is mapped to child nodes’ HeaderContentTemplate property. A value set here is inherited by child nodes if their ItemTemplate is left unset.

ItemTemplateSelector – A DataTemplatSelector which can be used to specify ItemTemplate based on specific items.

SelectionBoxType – Determines whether the selection and highlight boxes extend the entire width of the parent tree, or are restricted to the bounds of the node.

ShowHorizontalGridLines – Determines whether the horizontal grid lines are visible.

ShowRootLines – When true, root lines are displayed for the node. Default value is false. Note that if unset, this value will be bound to the ShowRootLines property of the parent Tree.

AdvTreeCell Interface

AdvTreeCell Events

BeforeSelected – A bubbling routed event raised before the value of IsSelected changes from false to true. Setting the event argument’s Handled property to true will cancel the selection.

EditBeginning – A bubbling routed event raised before the cell enters edit mode. Setting the event argument’s Handled property to true will cancel the edit.

EditCommitted – A bubbling routed event raised when changes are committed to the underlying data source.

EditEnded – Routed event raised when an edit operation is ended, whether or not the changes are committed.

Selected – A bubbling routed event raised when the value of IsSelected changes from false to true.

Unselected – A bubbling routed event raised when the value of IsSelected changes from true to false.

AdvTreeCell Methods

BeginEdit – Manually puts the cell into edit mode.

EndEdit – Manually ends edit mode with option to commit the edited value.

AdvTreeCell Properties

CLR Properties

IndexInRow – Gets the zero based index of this cell within the row or node.

IsConnected – Gets whether this cell is fully connected to its data source and column definition, and is ready to be displayed in the UI.

IsEditing – Returns true if the cell is currently in edit mode.

ParentNode – Gets the Node which is parent of this cell.

Dependency Properties

BeginEditTriggerMode – provides a means for defining what conditions are required for the cell to enter Edit mode. (Only applies when IsEditable is true.) More on node and cell editing is provided below.

CellDefinition – Provides access to the ColumnDefinition instance which defines the cell. This is a read only dependency property.

EditorStyle – Specifies a style which is applied to the embedded EditingContentControl which both displays and edits the cell’s content. Note that the editing control’s style can also be specified in the column definition via property CellEditorStyle. In either case, a value is not required. More on editing below.

EditTemplate – Optionally specifies a ControlTemplate to be applied to the ContentEditingControl which both displays and edits the cells content. More below.

IsEditable – When true, the cell’s content can be edited in place. See more about editing below.

IsHighlighted – Get or set whether the cell should be highlighted. Normally, this value is set when the mouse is over the cell.

IsSelectable – Determines whether the cell can be selected. The default value is true.

IsSelected – Gets or Sets whether the cell is currently selected. If IsSelectable is false, this property is ignored.

Control Templates

AdvTree Control Template

Here is the default ControlTemplate for AdvTree. You can use it as a starting point for customizing your own AdvTree template.

<ControlTemplate TargetType="{x:Type dc:AdvTree}">
    <Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}">
        <Grid Name="MainGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.Resources>
                <BooleanToVisibilityConverter x:Key="boolToVisibilityConverter" />
            </Grid.Resources>
            <Rectangle Height="{Binding ElementName=ColumnsPresenter, Path=HeaderHeight}" Width="0" Visibility="{Binding ElementName=ColumnsPresenter, Path=Visibility}" />
            <dc:ColumnsPresenter x:Name="ColumnsPresenter" Grid.RowSpan="2" ItemsSource="{TemplateBinding ColumnDefinitions}"                                 
                                    dc:DragDrop.DragAdornerTemplate="{DynamicResource {x:Static dc:AdvTree.ColumnHeaderDragAdornerTemplateKey}}"
                                    dc:DragDrop.DropAdornerTemplate="{DynamicResource {x:Static dc:AdvTree.ColumnHeaderDropAdornerTemplateKey}}"     
                                    Visibility="{Binding RelativeSource={RelativeSource Self}, Path=HasItems, Converter={StaticResource boolToVisibilityConverter}}" />
            <ScrollViewer Name="ScrollViewer" Grid.Row="1" Padding="0" Focusable="False" CanContentScroll="True" 
                            Style="{DynamicResource {x:Static dc:AdvTree.ScrollViewerStyleKey}}" 
                            IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}">
                <dc:VirtualizingTreePanel x:Name="ItemsHost" Margin="{TemplateBinding Padding}" />
            </ScrollViewer>
            <dc:PinnedColumnsSeparator Grid.RowSpan="2" Pin="Left" Visibility="Collapsed" HorizontalAlignment="Left" />
            <dc:PinnedColumnsSeparator Grid.RowSpan="2" Pin="Right" Visibility="Collapsed" HorizontalAlignment="Left" />
        </Grid>
    </Border>
</ControlTemplate>

AdvTreeNode Control Template

Here is the default ControlTemplate for AdvTreeNode. You can use it as a starting point for customizing your own.

<ControlTemplate TargetType="{x:Type dc:AdvTreeNode}">
    <ControlTemplate.Resources>
        <dc:NodePaddingToHeaderItemMarginConverger x:Key="paddingToMarginConverter" />
        <dc:CheckBoxTypeToIsThreeStateConverter x:Key="checkBoxThreeStateConverter" />
        <dc:CheckBoxTypeToVisibilityConverter x:Key="checkBoxVisibilityConverter" />
        <dc:NullableToVisibilityConverter x:Key="nullableToVisibilityConverter" />
    </ControlTemplate.Resources>
    <Grid Name="MainGrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
 
        <Border Name="BackgroundBorder" Grid.ColumnSpan="5" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" 
                Background="{TemplateBinding Background}" Margin="{Binding ElementName=Highlights, Path=Margin}" />
 
        <Grid Name="Highlights" Grid.ColumnSpan="5">
            <Border Name="SelectionBorder" Opacity="0" Style="{DynamicResource {x:Static dc:AdvTreeNode.FullSelectionBoxBorderStyleKey}}" />
            <Border Name="SelectedInactiveBorder" Opacity="0" Style="{DynamicResource {x:Static dc:AdvTreeNode.FullSelectionBoxBorderStyleKey}}" 
                    Background="{DynamicResource {x:Static dc:AdvTreeNode.InactiveSelectionBoxBackgroundKey}}" 
                    BorderBrush="{DynamicResource {x:Static dc:AdvTreeNode.InactiveSelectionBoxBorderBrushKey}}" />
            <Border Name="HighlightBorder" Opacity="0" Style="{DynamicResource {x:Static dc:AdvTreeNode.FullSelectionBoxBorderStyleKey}}" />
        </Grid>
 
        <Rectangle Name="GridLine" Grid.Row="1" Grid.ColumnSpan="5" Visibility="Collapsed" Margin="{Binding ElementName=Highlights, Path=Margin}"
                    Fill="{TemplateBinding HorizontalGridLineBrush}" Height="{TemplateBinding HorizontalGridLineHeight}" />
 
        <dc:AdvTreeCellPanel x:Name="CellPanel" Focusable="False" Visibility="Collapsed"  HorizontalAlignment="Left" Grid.Column="3" />
 
        <Grid Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Indent}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
            <ToggleButton Name="Expander" ClickMode="Press" Focusable="False"
                        IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded, Mode=TwoWay}"
                        Style="{TemplateBinding ExpanderButtonStyle}" />
        </Grid>
        <Image Name="Image" Grid.Column="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Focusable="False" Source="{TemplateBinding ImageSource}" 
                Visibility="{Binding RelativeSource={RelativeSource Self}, Path=Source, Converter={StaticResource nullableToVisibilityConverter}}"
                Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={StaticResource paddingToMarginConverter}}"/>
        <CheckBox Name="CheckBox" Grid.Column="2" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                    Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CheckBox, Converter={StaticResource checkBoxVisibilityConverter}}"
                    IsThreeState="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CheckBox, Converter={StaticResource checkBoxThreeStateConverter}}"
                    Margin="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={StaticResource paddingToMarginConverter}}"
                    IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked, Mode=TwoWay}"/>
 
        <dc:EditingContentControl x:Name="Editor" Grid.Column="3" Padding="{TemplateBinding Padding}" Style="{TemplateBinding EditorStyle}" 
                                    dc:ControlBehavior.CornerRadius="{Binding ElementName=SelectionBorder, Path=CornerRadius}"
                                    VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    EditorSettings="{TemplateBinding EditorSettings}" Validation.ErrorTemplate="{TemplateBinding Validation.ErrorTemplate}"
                                    ContentTemplate="{TemplateBinding HeaderTemplate}" ContentStringFormat="{TemplateBinding HeaderStringFormat}"
                                    Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Header, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
 
        <Rectangle Name="FocusRect" Grid.Column="1" Grid.ColumnSpan="3" Opacity="0" Stroke="Black" StrokeDashArray="1,2" SnapsToDevicePixels="True" />                      
 
        <dc:ColumnsPresenter x:Name="ColumnsPresenter" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="4" Visibility="Collapsed"
                            dc:DragDrop.IsDragSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ColumnDefinitions.AllowColumnReorder}" 
                            dc:DragDrop.IsDropTarget="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ColumnDefinitions.AllowColumnReorder}"    
                            dc:DragDrop.DragAdornerTemplate="{DynamicResource {x:Static dc:AdvTree.ColumnHeaderDragAdornerTemplateKey}}"
                            dc:DragDrop.DropAdornerTemplate="{DynamicResource {x:Static dc:AdvTree.ColumnHeaderDropAdornerTemplateKey}}"
                            ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ColumnDefinitions, Mode=OneWay}" />
 
        <AdornerDecorator Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="4">
            <dc:ItemsControlPanel x:Name="ItemsHost" Visibility="Collapsed" />
        </AdornerDecorator>
 
        <Rectangle Name="BottomGridLine" Grid.Row="2" Grid.ColumnSpan="5" Opacity="0" VerticalAlignment="Bottom" 
                    Visibility="{Binding ElementName=ColumnsPresenter, Path=Visibility}"
                    Margin="{Binding ElementName=GridLine, Path=Margin}"
                    Fill="{TemplateBinding HorizontalGridLineBrush}" Height="{TemplateBinding HorizontalGridLineHeight}" />
 
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal" />
                <VisualState Name="Disabled" />
            </VisualStateGroup>
            <VisualStateGroup Name="ExpandedStates">
                <VisualState Name="Collapsed" />
                    <VisualState Name="Expanded">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsHost" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="SelectedStates">
                <VisualState Name="Unselected" />
                <VisualState Name="Selected">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="SelectionBorder" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState Name="CellSelectedWithin" />
                <VisualState Name="SelectedInactive">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="SelectedInactiveBorder" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="HighlightedStates">
                <VisualState Name="NotHighlighted" />
                <VisualState Name="IsHighlighted">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="HighlightBorder" Storyboard.TargetProperty="Opacity" To="1" Duration="0" />
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="SelectionBoxStates">
                <VisualState Name="FullSelectionBox" />
                <VisualState Name="NoSelectionBox">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Highlights" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState Name="ContainedSelectionBox">
                    <Storyboard>
                        <Int32Animation Storyboard.TargetName="Highlights" Storyboard.TargetProperty="(Grid.Column)" To="1" Duration="0" />
                        <Int32Animation Storyboard.TargetName="Highlights" Storyboard.TargetProperty="(Grid.ColumnSpan)" To="3" Duration="0" />
                        <Int32Animation Storyboard.TargetName="GridLine" Storyboard.TargetProperty="(Grid.ColumnSpan)" To="4" Duration="0" />
                        <ThicknessAnimation Storyboard.TargetName="GridLine" Storyboard.TargetProperty="Margin" To="0" Duration="0" />
                        <Int32Animation Storyboard.TargetName="BottomGridLine" Storyboard.TargetProperty="(Grid.ColumnSpan)" To="4" Duration="0" />
                        <Int32Animation Storyboard.TargetName="BackgroundBorder" Storyboard.TargetProperty="(Grid.ColumnSpan)" To="4" Duration="0" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="HasCellsStates">
                <VisualState Name="NoCells">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Editor" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CellPanel" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState Name="HasCells">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Editor" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CellPanel" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="FocusStates">
                <VisualState Name="Unfocused" />
                <VisualState Name="Focused">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="ShowHorizontalGridLines" Value="True">
            <Setter TargetName="GridLine" Property="Visibility" Value="Visible" />
            <Setter TargetName="BottomGridLine" Property="Opacity" Value="1" />
        </Trigger>
        <Trigger Property="HasItems" Value="False">
            <Setter TargetName="Expander" Property="Visibility" Value="Hidden" />
        </Trigger>
        <Trigger Property="CanUserCollapse" Value="False">
            <Setter TargetName="Expander" Property="Visibility" Value="Collapsed" />
        </Trigger> 
        <Trigger Property="CanHaveItems" Value="False">
            <Setter TargetName="Expander" Property="Visibility" Value="Collapsed" />
        </Trigger>
        <Trigger Property="SelectionBoxType" Value="Contained">
            <Setter TargetName="SelectionBorder" Property="Style" Value="{DynamicResource {x:Static dc:AdvTreeNode.ContainedSelectionBoxBorderStyleKey}}" />
            <Setter TargetName="HighlightBorder" Property="Style" Value="{DynamicResource {x:Static dc:AdvTreeNode.ContainedSelectionBoxBorderStyleKey}}" />
            <Setter TargetName="SelectedInactiveBorder" Property="Style" Value="{DynamicResource {x:Static dc:AdvTreeNode.ContainedSelectionBoxBorderStyleKey}}" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

AdvTreeCell Control Template

Here is the default ControlTemplate for AdvTreeCell. You can use it as a starting point for customizing your own AdvTreeCell template.

<ControlTemplate TargetType="dc:AdvTreeCell">
    <Grid Name="MainGrid" Background="Transparent">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" />
 
        <Border Name="SelectedBorder" Opacity="0" Style="{DynamicResource {x:Static dc:AdvTreeCell.SelectionBoxBorderStyleKey}}" />
        <Border Name="SelectedInactiveBorder" Opacity="0" Style="{DynamicResource {x:Static dc:AdvTreeCell.SelectionBoxBorderStyleKey}}"
                Background="{DynamicResource {x:Static dc:AdvTreeCell.InactiveSelectionBoxBackgroundKey}}" 
                BorderBrush="{DynamicResource {x:Static dc:AdvTreeCell.InactiveSelectionBoxBorderBrushKey}}" />
        <Border Name="HighlightBorder" Opacity="0" Style="{DynamicResource {x:Static dc:AdvTreeCell.SelectionBoxBorderStyleKey}}" />
 
        <Rectangle Name="FocusRect" Opacity="0" Stroke="Black" StrokeDashArray="1,2" SnapsToDevicePixels="True" />
 
        <Rectangle Grid.Column="1" VerticalAlignment="Stretch"
                    Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CellDefinition.ParentCollection.ShowGridLines, Converter={StaticResource boolToVisibilityConverter}}"
                    Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CellDefinition.GridLineBrush}" 
                    Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CellDefinition.GridLineWidth}" />
 
        <dc:EditingContentControl x:Name="Editor" Style="{TemplateBinding EditorStyle}" Padding="{TemplateBinding Padding}"
                                    Validation.ErrorTemplate="{TemplateBinding Validation.ErrorTemplate}" 
                                    dc:ControlBehavior.CornerRadius="{Binding ElementName=SelectedBorder, Path=CornerRadius}"
                                    VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    EditorSettings="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CellDefinition.EditorSettings}"
                                    ContentTemplate="{TemplateBinding ContentTemplate}" ContentStringFormat="{TemplateBinding ContentStringFormat}"
                                    Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
 
 
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal" />
                <VisualState Name="Disabled" />
                <VisualState Name="Highlighted">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="HighlightBorder" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="SelectionStates">
                <VisualState Name="Unselected" />
                <VisualState Name="Selected">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="SelectedBorder" Storyboard.TargetProperty="Opacity" Duration="00:00:00.03" To="1" />
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState Name="SelectedByColumn">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="SelectedBorder" Storyboard.TargetProperty="Opacity" Duration="00:00:00.03" To="1" />
                    </Storyboard>
                </VisualState>
                <VisualState Name="SelectedInactive">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="SelectedInactiveBorder" Storyboard.TargetProperty="Opacity" Duration="00:00:00.03" To="1" />
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Visibility">
                            <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="FocusStates">
                <VisualState Name="Unfocused" />
                <VisualState Name="Focused">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="FocusRect" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
    <ControlTemplate.Triggers>
        <MultiDataTrigger>
            <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=CellDefinition.ParentCollection.ShowGridLines}" Value="True" />
                <Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=dc:AdvTreeNode}, Path=ShowHorizontalGridLines}" Value="True" />
            </MultiDataTrigger.Conditions>
            <Setter TargetName="Editor" Property="Margin" Value="-1" />
            <Setter TargetName="Editor" Property="Padding" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Padding, Converter={StaticResource additionConverter}, ConverterParameter=1}" />
        </MultiDataTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

ColumnsPresenter Control Template

Here are the default ControlTemplates for ColumnsPresenter and ColumnPresenter. You can use them as starting place for customizing your own templates for these controls.

<ControlTemplate TargetType="{x:Type ctrls:ColumnsPresenter}">
    <Grid Name="MainGrid">
        <Grid.ContextMenu>
            <ContextMenu ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ColumnDefinitions}" 
                            ItemContainerStyle="{DynamicResource {x:Static ctrls:ColumnsPresenter.ContextMenuItemStyleKey}}" />
        </Grid.ContextMenu>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ContentPresenter Name="Label" Content="{TemplateBinding Label}" ContentTemplate="{TemplateBinding LabelTemplate}" />
        <Border Grid.Row="1" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
            <Grid>
                <Rectangle VerticalAlignment="Top" Height="{TemplateBinding HeaderHeight}" Fill="{TemplateBinding HeaderBackground}" />
                <ItemsPresenter />
                <Border VerticalAlignment="Top" Height="{TemplateBinding HeaderHeight}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding HeaderBorderThickness}" />
            </Grid>
        </Border>
    </Grid>
    <ControlTemplate.Triggers>
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ColumnDefinitions.IsContextMenuEnabled}" Value="False">
            <Setter TargetName="MainGrid" Property="Grid.ContextMenu" Value="{x:Null}" />
        </DataTrigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate TargetType="ctrls:ColumnPresenter">
    <Grid Background="Transparent" SnapsToDevicePixels="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <ctrls:ColumnHeader x:Name="Header" Visibility="{Binding ShowHeader, Converter={StaticResource boolToVisibilityConverter}}" />
        <Thumb Name="ResizeThumb" Width="6" HorizontalAlignment="Right" Cursor="SizeWE" 
                Visibility="{Binding AllowColumnResize, Converter={StaticResource boolToVisibilityConverter}}">
            <Thumb.Template>
                <ControlTemplate>
                    <Grid Background="Transparent" />
                </ControlTemplate>
            </Thumb.Template>
        </Thumb>
        <Border Name="ColumnBorder" Grid.Row="1" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" />
        <Rectangle Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Top"
                    Height="{Binding RelativeSource={RelativeSource AncestorType=ctrls:AdvTabularControl}, Path=Padding, Converter={StaticResource thicknessToDoubleConverter}, ConverterParameter=Top}" 
                    Fill="{Binding GridLineBrush}" Width="{Binding GridLineWidth}" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="Pin" Value="Right">
            <Setter TargetName="ResizeThumb" Property="HorizontalAlignment" Value="Left" />
            <Setter TargetName="ResizeThumb" Property="Margin" Value="-6,0,0,0" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate TargetType="ctrls:ColumnHeader">
    <ControlTemplate.Resources>
    </ControlTemplate.Resources>
    <Grid Background="Transparent">
        <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" />
        <Border Name="CellSelectedBorder" Margin="-1,0,0,0" Opacity="0" BorderThickness="1,0,1,1" BorderBrush="{DynamicResource {x:Static ctrls:ColumnPresenter.CellSelectedHeaderBorderBrushKey}}"
                Background="{DynamicResource {x:Static ctrls:ColumnPresenter.CellSelectedHeaderBackgroundKey}}" />
        <Border Name="ColumnSelectedBorder" Margin="-1,0,0,0" Opacity="0" BorderThickness="1,0,1,1" BorderBrush="{DynamicResource {x:Static ctrls:ColumnPresenter.ColumnSelectedHeaderBorderBrushKey}}"
                Background="{DynamicResource {x:Static ctrls:ColumnPresenter.ColumnSelectedHeaderBackgroundKey}}" />
        <Border Name="SelectedInactiveBorder" Margin="-1,0,0,0" Opacity="0" BorderThickness="1,0,1,1" BorderBrush="{DynamicResource {x:Static ctrls:ColumnPresenter.SelectedInactiveHeaderBorderBrushKey}}"
                Background="{DynamicResource {x:Static ctrls:ColumnPresenter.SelectedInactiveHeaderBackgroundKey}}" />
        <Border Name="PressedBorder" Margin="-1,0,0,0" Opacity="0" BorderThickness="1,0,1,1" BorderBrush="{DynamicResource {x:Static ctrls:ColumnPresenter.HeaderHighlightBorderBrushKey}}"
                Background="{DynamicResource {x:Static ctrls:ColumnPresenter.HeaderPressedBackgroundKey}}" />
        <Border Name="HighlightBorder" Margin="-1,0,0,0" Opacity="0" BorderThickness="1,0,1,1" BorderBrush="{DynamicResource {x:Static ctrls:ColumnPresenter.HeaderHighlightBorderBrushKey}}"
                Background="{DynamicResource {x:Static ctrls:ColumnPresenter.HeaderHighlightBackgroundKey}}" />
        <ContentPresenter Name="Presenter" Margin="{TemplateBinding Padding}" 
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
        <Control Name="SortGlyph" Grid.Column="1" Style="{DynamicResource {x:Static ctrls:ColumnPresenter.ColumnSortGlyphStyleKey}}" />
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup Name="CommonStates">
                <VisualState Name="Normal" />
                <VisualState Name="Disabled" />
                <VisualState Name="Highlighted">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="HighlightBorder" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                    </Storyboard>
                </VisualState>
                <VisualState Name="Pressed">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="PressedBorder" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
            <VisualStateGroup Name="SelectionStates">
                <VisualState Name="Unselected" />
                <VisualState Name="ColumnSelected">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="ColumnSelectedBorder" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                    </Storyboard>
                </VisualState>
                <VisualState Name="CellSelectedWithin">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="CellSelectedBorder" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                    </Storyboard>
                </VisualState>
                <VisualState Name="SelectedInactive">
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetName="SelectedInactiveBorder" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</ControlTemplate>

The following is the Style applied to the ContextMenu that is created by default for ColumnsPresenter when IsContextMenuActive = true.

<Style x:Key="{x:Static ctrls:ColumnsPresenter.ContextMenuItemStyleKey}" TargetType="MenuItem">
    <Style.Resources>
        <ctrls:VisibilityToBooleanConverter x:Key="visibilityToBoolConverter" />
    </Style.Resources>
    <Setter Property="Foreground" Value="{DynamicResource {x:Static ctrls:MenuResources.MenuItemForegroundKey}}" />
    <Setter Property="Padding" Value="{DynamicResource {x:Static ctrls:MenuResources.MenuItemPaddingKey}}" />
    <Setter Property="IsCheckable" Value="True" />
    <Setter Property="IsChecked" Value="{Binding Visibility, Converter={StaticResource visibilityToBoolConverter}, Mode=TwoWay}" />
    <Setter Property="Header" Value="{Binding Header}" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsLocked}" Value="True">
            <Setter Property="Visibility" Value="Collapsed" />
        </DataTrigger>
    </Style.Triggers>
</Style>

Related posts:

  1. Brush Control Quick Start Guide
  2. WPF Color Control Quick Start Guide
  3. WPF AdvGrid Quick Start Guide
  4. Circular Progress Control (WPF) Quick Start Guide
  5. WPF EnumPicker