Click here to Skip to main content
14,119,858 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

15.2K views
213 downloads
7 bookmarked
Posted 30 Jan 2017
Licenced CPOL

WPF DataGrid with SharedSizeGroup Columns Property

, 31 Jan 2017
Rate this:
Please Sign up or sign in to vote.
This article presents an attached behaviour for the WPF DataGrid control which allows multiple columns to share the same width, and columns to shrink to fit their content.

Introduction

The WPF DataGrid is a powerful control for displaying lists of data with multiple fields, but there are notable shortcomings to the standard layout properties and methods. Attached behaviours provide a powerful and reusable mechanism to extend the behaviour and appearance of existing controls.

This article presents an attached behaviour for the WPF DataGrid control which adds the following features:

  • Configure groups of columns that share the same width (as per the WPF Grid sharedsizegroup property).
  • Shrink the columns to fit their content. By default, columns can expand, but they do not shrink.
  • Enable/disable extended formatting.

All three features are configured in the XAML and support binding.

This article includes a simple test application demonstrating the use of the attached behaviour.

Background

You should be familiar with WPF, and basic concepts such as styles and resource dictionaries.

You do not need to understand attached behaviours to use the supplied code, but if you wish to learn about them, then I strongly recommend that you read this excellent article:

The current article is loosely based on a post by Fredrik Hedblad where he describes an attached behaviour to resize a ComboBox control to its content. The post can be found on this page:

Using the Code

The first step is to reference the attached behaviour in the XAML. The code is in the DataGridLayoutApp.View namespace, hence the following attribute needs to be added to the window hosting the DataGrid control:

xmlns:view="clr-namespace:DataGridLayoutApp.View"

The data grid uses the attached behaviour by setting attributes, as in this example:

<DataGrid Grid.Row="4" Grid.Column="0" 

ItemsSource="{Binding Regions}" 

SelectedItem="{Binding SelectedRegion, Mode=TwoWay}"

        Style="{StaticResource styleDataGrid}" 

        CanUserSortColumns="False" 

        IsReadOnly="True" Margin="0" 

        HorizontalAlignment="Left"

        view:DataGridLayoutBehavior.DataGridLayout="true" 

        view:DataGridLayoutBehavior.Enabled="true" 

        view:DataGridLayoutBehavior.ShrinkColumnsToFit="true">
    <DataGrid.Columns >
        <DataGridTextColumn Header="Text" 

        Binding="{Binding Path=Text}"/>
        <DataGridTextColumn Header="Left" 

        MinWidth="20" Binding="{Binding Path=Left}" 

         view:DataGridLayoutBehavior.SharedSizeGroup="X" />
        <DataGridTextColumn Header="Top" 

        Binding="{Binding Path=Top}" 

         view:DataGridLayoutBehavior.SharedSizeGroup="X" />
        <DataGridTextColumn Header="Right" 

        Binding="{Binding Path=Right}" 

         view:DataGridLayoutBehavior.SharedSizeGroup="X" />
        <DataGridTextColumn Header="Bottom" 

        Binding="{Binding Path=Bottom}" 

         view:DataGridLayoutBehavior.SharedSizeGroup="X" />
    </DataGrid.Columns>
</DataGrid>

It is assumed that a view model has been assigned to the view's data context.

The above data grid displays the list of items in the Regions collection. Each item contains Text, Left, Top, Right and Bottom attributes.

The following attribute enables the data grid layout attached behaviour:

view:DataGridLayoutBehavior.DataGridLayout="true"

The following attribute enables the formatting:

view:DataGridLayoutBehavior.Enabled="true"

The following attribute shrinks the data grid columns to fit their content:

view:DataGridLayoutBehavior.ShrinkColumnsToFit="true"

By default, columns expand to fit their content, but they do not shrink.

Finally, the following attribute of the DataGridTextColumn element defines a shared width group:

<DataGridTextColumn Header="Left" Binding="{Binding Path=Left}" 
view:DataGridLayoutBehavior.SharedSizeGroup="X" /> 

Four of the five columns have this attribute set equal to "X" indicating that they should all share the same width. Were two of the columns to have this attribute set to "Y", they would belong to a second shared width group.

The Attached Behaviour Explained

You do not need to read this section if all you want to do is use the attached behaviour.

There are two key classes.

The DataGridLayoutBehavior Class

This class implements four attached properties which control the behaviour of the data grid layout.

The DataGridLayout attached property enables or disables the behaviour. When the property is set, the code invokes an extension method on the data grid instance. This is described later on. This property does not support binding.

The Enabled attached property enables and disables the extended formatting. This property supports binding.

The ShrinkColumnsToFit attached property enables and disables the shrinking of columns to fit their content. This property supports binding.

And lastly, the SharedSizeGroup property defines data grid column shared width groups. This property supports binding.

The DataGridExtensionMethods Class

The key method of this class is the ExtendedLayout extension method, which extends a DataGrid instance. This method installs an event handler which the data grid invokes each time the items change:

dataGrid.ItemContainerGenerator.ItemsChanged += new ItemsChangedEventHandler(eventHandler);

It also invokes the event handler to initialize the data grid format.

The event handler is defined as an anonymous method which performs the required actions. It queries the values of the attached properties to determine how it should modify the data grid layout:

  • Enabled
  • ShrinkColumnsToFit
  • SharedWidthKey

The Demonstration App

The app demonstrates data grids with and without the attached behaviour.

The main window contains:

  • A data grid using the attached behaviour:
    • The first column with auto width
    • Four columns in a shared width group
    • Columns expanding and shrinking to fit the content
  • A data grid
  • A fixed width stack panel containing a data grid with the width of four columns set to "*"

The first and second data grids contrast the attached behaviour to the 'naked' grid. The third data grid demonstrates an alternative way to have four columns with the same width, but not fitted to the content.

Sample Code

The source code for the attached behaviour and the demonstration app can be downloaded here.

Further Enhancements

It is quite likely that you will want slightly different behaviour from that implemented, given that you will have different needs. The behavior can be extended quite easily by defining additional attached properties, and modifying the DataGridExtensionMethods.ExtendedLayout method.

The current implementation of SharedSizeGroup does not fully replicate the Grid SharedSizeGroup property, as it does not allow columns in separate data grids to share the same width. This feature is left as an 'exercise for the reader'.

Issues

There is a known minor bug. When a row is removed, column widths do not automatically shrink to fit the modified content. However, when a row is subsequently added, the columns shrink to fit the content. Curiously, this bug whilst present in the demonstration app, is not present in our application.

Performance may be an issue with large datasets.

The current implementation was written for our application which has read only data grids. It does not work so well for an editable data grid, where the user can resize columns, and edit the content of cells. Improvements in this area are left as an 'exercise for the reader'.

History

  • 30th January, 2017: First version release
  • 31st January, 2017: Added link to sample code
  • 1 February, 2017: Added the sample code as a ZIP file => this site does not support 7ZIP.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Leif Simon Goodwin
United Kingdom United Kingdom
C#/WPF/C++ Windows developer

You may also be interested in...

Comments and Discussions

 
GeneralNo download avaiable Pin
sditt31-Jan-17 2:39
membersditt31-Jan-17 2:39 
GeneralRe: No download avaiable Pin
Leif Simon Goodwin31-Jan-17 5:27
memberLeif Simon Goodwin31-Jan-17 5:27 
GeneralRe: No download avaiable Pin
Bryian Tan31-Jan-17 5:44
mveBryian Tan31-Jan-17 5:44 
GeneralRe: No download avaiable Pin
Leif Simon Goodwin31-Jan-17 21:08
memberLeif Simon Goodwin31-Jan-17 21:08 
QuestionExample Pin
leluc4230-Jan-17 18:53
memberleluc4230-Jan-17 18:53 
AnswerRe: Example Pin
Leif Simon Goodwin30-Jan-17 21:21
memberLeif Simon Goodwin30-Jan-17 21:21 
GeneralRe: Example Pin
leluc426-Feb-17 23:22
memberleluc426-Feb-17 23:22 
GeneralRe: Example Pin
Leif Simon Goodwin7-Feb-17 21:49
memberLeif Simon Goodwin7-Feb-17 21:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190518.1 | Last Updated 1 Feb 2017
Article Copyright 2017 by Leif Simon Goodwin
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid