Tree List View
A tree and a grid in one control: rows that nest, expand and collapse like a
TreeView, laid out in resizable, sortable, reorderable columns like a
ListView in grid view.
Assembly
| Assembly | Binarymission.WPF.Controls.BinaryTreeListView.dll |
| Root namespace | Binarymission.WPF.Controls.TreeControls |
| Target frameworks | .NET Framework 4.8, .NET 6 / 8 / 10 |
| Depends on | Skinning |
Overview
Use it wherever data has both a hierarchy and several facts per row: a project plan with owners and dates, a file system with sizes and types, a chart of accounts with balances, an organisation with roles and locations.
Columns
Add a GridViewColumn to Columns for each column, exactly as
for a GridView: give it a GridViewColumn.DisplayMemberBinding for
plain text, or a GridViewColumn.CellTemplate for anything richer. One column
carries the tree – the indent, the expander and the connecting lines. It is the first column
unless you choose another with TreeListViewColumnIndex or
TreeListViewColumn. The rows line up
across every level of the tree, and follow the headings when the user resizes or drags
them.
Rows
There are two ways to give the control its rows, and every feature works with both.
- Bind it. Set
ItemsControl.ItemsSourceto your top-level objects, and setItemsControl.ItemTemplateto aHierarchicalDataTemplatewhoseItemsSourcenames each object's children. The columns' bindings are evaluated against each object. - Build it. Add
BinaryTreeListViewItemnodes toItemsControl.Items, each with its row object inHeaderand its child nodes in its ownItems.
Sorting
With AllowsColumnSorting on, a click on a heading sorts by that column and a
second click reverses it; SortByColumn and ClearColumnSort do the
same from code. Each branch is sorted within itself, so children stay under their parents.
A column that draws its cells with a template has no binding to sort by – name the property
with SetSortMemberPath.
Selection
Single selection works as in any tree view, through TreeView.SelectedItem
and TreeView.SelectedItemChanged. Turn on IsMultiSelectionEnabled
to let Ctrl+click add and remove rows, and IsShiftMultiSelectionEnabled as well
to let Shift+click select every row on show between the last row clicked and this one, at any
depth. The rows selected that way are in MultiSelectedItems.
Appearance
Theme applies one of eight built-in colour schemes in a single setting, and
any brush can then be set on its own to depart from it. Alternate-row striping
(AlternateRowBackgroundBrush) counts the rows as they are drawn, so it stays
correct as branches open, close and sort. The expander can be drawn in five shapes
(ExpanderGlyph), the connecting lines solid or dotted, and the column headings in
colours of your own. The default colour given for each brush is the one used with no
Binarymission skin in force; a skin (Binarymission.WPF.Skinning) supplies its own.
Getting started
A bound tree of folders and files in XAML. Each FolderRow has
Name, Kind, Size and Modified properties and a Children
collection; the window's data context exposes the top-level rows as Roots.
<Window x:Class="Explorer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tlv="clr-namespace:Binarymission.WPF.Controls.TreeControls;assembly=Binarymission.WPF.Controls.BinaryTreeListView"
Title="Explorer" Width="900" Height="560">
<tlv:BinaryTreeListView ItemsSource="{Binding Roots}"
TreeListViewColumnIndex="0"
AllowsColumnSorting="True"
AllowsColumnReorder="True"
IsMultiSelectionEnabled="True"
IsShiftMultiSelectionEnabled="True"
ExpanderGlyph="Chevron"
Theme="Office">
<tlv:BinaryTreeListView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}" />
</tlv:BinaryTreeListView.ItemTemplate>
<tlv:BinaryTreeListView.Columns>
<GridViewColumn Header="Name" Width="320" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Type" Width="140" DisplayMemberBinding="{Binding Kind}" />
<GridViewColumn Header="Size" Width="100" DisplayMemberBinding="{Binding Size, StringFormat={}{0:N0} KB}" />
<GridViewColumn Header="Modified" Width="160" DisplayMemberBinding="{Binding Modified, StringFormat=d}" />
</tlv:BinaryTreeListView.Columns>
</tlv:BinaryTreeListView>
</Window>The same control built in code, with the rows added as nodes rather than bound. The row objects can be any class with public properties.
using System.Windows.Controls;
using System.Windows.Data;
using Binarymission.WPF.Controls.TreeControls;
public sealed class TaskRow
{
public string Name { get; set; }
public string Owner { get; set; }
public int Percent { get; set; }
}
BinaryTreeListView plan = new BinaryTreeListView
{
AllowsColumnSorting = true,
IsMultiSelectionEnabled = true,
Theme = BinaryTreeListViewTheme.Office
};
plan.Columns.Add(new GridViewColumn { Header = "Task", Width = 280, DisplayMemberBinding = new Binding("Name") });
plan.Columns.Add(new GridViewColumn { Header = "Owner", Width = 140, DisplayMemberBinding = new Binding("Owner") });
plan.Columns.Add(new GridViewColumn { Header = "Done", Width = 80, DisplayMemberBinding = new Binding("Percent") { StringFormat = "{0}%" } });
plan.TreeListViewColumnIndex = 0;
BinaryTreeListViewItem design = new BinaryTreeListViewItem
{
Header = new TaskRow { Name = "Design", Owner = "Priya", Percent = 60 },
IsExpanded = true
};
design.Items.Add(new BinaryTreeListViewItem { Header = new TaskRow { Name = "Wireframes", Owner = "Priya", Percent = 100 } });
design.Items.Add(new BinaryTreeListViewItem { Header = new TaskRow { Name = "Visual design", Owner = "Tom", Percent = 20 } });
plan.Items.Add(design);API reference
Binarymission.WPF.Controls.TreeControls
class BinaryCheckBox | A check box whose box, border and check mark can each be coloured for every state - normal, pointer over, pressed and disabled - without writing a template. |
class BinaryTreeListView | A tree and a grid in one control: rows that nest, expand and collapse like a TreeView, laid out in resizable, sortable, reorderable columns like a ListView in grid view. |
enum BinaryTreeListViewExpanderGlyph | The shapes the expand / collapse control can be drawn as. |
class BinaryTreeListViewItem | One row of a BinaryTreeListView: its cells, its expander and the rows beneath it. |
enum BinaryTreeListViewTheme | The built-in colour schemes a BinaryTreeListView can draw itself in. |
Binarymission.WPF.Controls.TreeControls.Converters
class BinaryTreeListConnectingLineConverter | Tells a row's template whether the row is the last of its siblings, which is where a connecting line stops rather than carrying on down. |
class BinaryTreeListConnectingRootLineConverter | Tells a row's template whether the row is a top-level row, which has no parent to draw a line up to. |
class BooleanToCornerRadiusConverter | Turns a bool into a CornerRadius, so a switch in the control can round a border the template draws. |
class PathToImageSourceConverter | Turns an image's address - a file path, a pack URI or a web address, as a string or a Uri - into an ImageSource, so a row object can name its icon as text. |