Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Embedding Controls in WPF DataGrid

0.00/5 (No votes)
24 Sep 2009 1  
Sample program shows how to embed controls in a WPF DataGrid using VB.NET

Introduction

WPF ListView and DataGrid controls are very powerful but rather mysterious to program in VB.NET (VS 2010 Beta 1) without using XAML. This article shows how to embed various controls into cells of ListView and DataGrid. The sample program demonstrates how to embed TextBlock, TextBox, FlowDocument, and RichTextBox. The data source for the demonstration program is a LINQ query that obtains process information (process name, id, etc.). The grids are built using either the LINQ query either directly or indirectly via DataTables. Data binding, control factories, IValueConverter and INotifyPropertyChange are used to build the sample program. The demonstration program presents a matrix of options which are used to generate grids of various data sources and data types.

Background

While working on a project which required displaying rich text in a grid, I became very frustrated by the lack of information about the WPF DataGrid control. I wanted to build the control in code (VB.NET, no XAML). There were few examples. Hence I decided to create a mega sample program that demonstrates many combinations of LINQ queries, controls and data binding.

Using the Code 

The attached program uses three different ways to capture a LINQ query. The query uses GetProcess to obtain information about the currently running processes.

  1. Captures a query result to an anonymous type.
  2. Captures a query result as an instance of a class (ProcessInfo).
  3. Uses the above to create a collection class (ProcessInfoCollection) which uses INotifyPropertyChange to enable dynamic binding. 

The user can select any or all of the above LINQ query methods to create a binding. The binding can be used to directly feed ListView or DataGrid controls or indirectly by creating DataTables from the query and then binding the DataTables. The program allows the user to create DataTables of nine data types.

  1. Source data type. The DataTable columns inherit their type from the data source.
  2. All columns are String types.
  3. All columns are TextBlock controls. TextBlocks have some rich text ability. Since TextBlocks can't be created using FrameworkElementFactory (they lack a InlinesProperty), the program contains BindableTextBlock class to allow FrameworkElementFactory to work.
  4. All columns are BindableTextBlocks.
  5. All columns are TextBoxes. TextBox lacks rich text ability.
  6. All columns are a string representation of FlowDocument.
  7. All columns are FlowDocument controls.
  8. All columns are RichTextBox controls. Since RichTextBoxes can't be created using FrameworkElementFactory (they lack a DocumentProperty), the program contains BindableRichTextBox class to allow FrameworkElementFactory to work. 
  9. All columns are BindableRichTextBox

The user can select the data type of the columns of the ListView or DataGrid control. Essentially the same choices as above. This means that any of the above data types may have to be converted into any of the others (e.g. TextBlock into RichTextBox). All these combinations are handled by the Convert method of the IValueConverter interface.

To demonstrate how to style individual cells, the user can select text styling according to the contents of the cell (using regular expressions). For example, all process names beginning with the letter b have their process names bolded, names beginning with i are italicized, letters beginning with r have a red foreground, and processes with a u are underlined. Otherwise, all cells are given black foreground and light gray backgrounds in the FrameworkElementFactory code.

The Refresh button will cause new data to appear in the grids but only for the INotify class when fed directly into the ListView or DataGrid (not via a DataTable).

The final option allows the user to generate windows of ListViews and/or DataGrids. Be careful, it's easy to get carried away with options thus generating dozens of windows which will deplete your computer of CPU and memory.

To build the project, just create a new VS 2010 WPF Application project and paste/copy Window1.xaml.vb and Window1.xaml. There are no references to add.

Points of Interest

The key to the program's magic is the Convert method of IValueConverter interface. The method contains the goodness to convert from many types (datatypes and controls) to other types. Other challenges were dynamic binding (INotifyPropertyChange) as implemented in the ProcessInfoCollection class, column binding, and supporting the three types of LINQ results.

History

  • 24-Sept-2009: Version 0.1

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here