HomeSearch

WPF DataGrid Examples: ItemsSource

Use the WPF DataGrid to display an editable table. Access the ItemsSource property.

DataGrid.

A DataGrid is a table. It has rows and columns. We use properties on DataGrid, such as ItemsSource, to populate it. We also specify how users edit its data, and how it visually renders that data.

ItemsSource.

This example uses DataGrid and its ItemsSource property with a List. First, create a WPF project and drag a DataGrid to your window. In the XAML, please add the attribute "Loaded" to the "DataGrid" element.

Then: Visual Studio will create the DataGrid_Loaded event handler. This is where we assign the ItemsSource property.

Loaded: In the DataGrid_Loaded method, we create a List of Dog objects. These objects are automatically traversed by the DataGrid.

In the Dog class,

please notice how there are two public properties: Name (a string) and Size (an int). In the resulting DataGrid, each property becomes a column header. So it has "Name" and "Size" columns.

ItemSource: The ItemsSource property accepts only an IEnumerable. Many types (like array and List) implement the IEnumerable interface.

Tip: If the IEnumerable (that is used with ItemSource) uses objects, each object's properties are evaluated.

IEnumerable

Caution: ItemsSource does not support a List of arrays. It is better, and more efficient, to simply use objects (such as the Dog class).

Example markup: XAML <Window x:Class="WpfApplication14.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <DataGrid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Loaded="DataGrid_Loaded"/> </Grid> </Window> Example code: C# using System.Collections.Generic; using System.Windows; using System.Windows.Controls; class Dog { public string Name { get; set; } public int Size { get; set; } public Dog(string name, int size) { this.Name = name; this.Size = size; } } namespace WpfApplication14 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void DataGrid_Loaded(object sender, RoutedEventArgs e) { // ... Create a List of objects. var items = new List<Dog>(); items.Add(new Dog("Fido", 10)); items.Add(new Dog("Spark", 20)); items.Add(new Dog("Fluffy", 4)); // ... Assign ItemsSource of DataGrid. var grid = sender as DataGrid; grid.ItemsSource = items; } } }

Color.

A grid is sometimes hard to read—the rows are hard to follow with your eyes. The DataGrid offers the AlternatingRowBackground attribute to make rows more distinguished in a visual way.

Tip: I recommend this option for most programs that use DataGrids of nontrivial size. The color shown (Coral) is not ideal.

Example markup 2: XAML <Window x:Class="WpfApplication14.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <DataGrid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" AlternatingRowBackground="Coral" Loaded="DataGrid_Loaded"/> </Grid> </Window>

SelectedItems.

How can you access the selected cells (or objects) in a DataGrid? With the SelectedItems property, we get a List of these cells. In this example, we populate the DataGrid with a List of Dog objects.

Then: We hook up the SelectionChanged event by adding the DataGrid_SelectionChanged method.

In SelectionChanged,

we loop over the items in the SelectedItems List. And we cast each object to its original type (in this program, the Dog type). Finally we join those strings together and display them on the window.

Note: I apologize for the complex example. The important part to examine is the DataGrid_SelectedChanged method.

Example markup 3: XAML <Window x:Class="WpfApplication14.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <DataGrid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" SelectionChanged="DataGrid_SelectionChanged" Loaded="DataGrid_Loaded"/> </Grid> </Window> Example code 3: C# using System.Collections.Generic; using System.Windows; using System.Windows.Controls; class Dog { public string Name { get; set; } public int Size { get; set; } public Dog(string name, int size) { this.Name = name; this.Size = size; } } namespace WpfApplication14 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void DataGrid_Loaded(object sender, RoutedEventArgs e) { // ... Create. var items = new List<Dog>(); items.Add(new Dog("Fido", 10)); items.Add(new Dog("Spark", 20)); items.Add(new Dog("Fluffy", 4)); items.Add(new Dog("Rover", 100)); items.Add(new Dog("Mister Mars", 30)); // ... Assign. var grid = sender as DataGrid; grid.ItemsSource = items; } private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) { // ... Get SelectedItems from DataGrid. var grid = sender as DataGrid; var selected = grid.SelectedItems; // ... Add all Names to a List. List<string> names = new List<string>(); foreach (var item in selected) { var dog = item as Dog; names.Add(dog.Name); } // ... Set Title to selected names. this.Title = string.Join(", ", names); } } }

CellEditEnding.

The DataGrid supports editing of its cells by the user. When the edit is finished by the user, the CellEditEnding event is triggered. And in this C# method, we can cancel the edit. This is useful if we detect an invalid entry.

Here: We use the program as in previous examples, but we omit some repeated parts of the source file.

Tip: We can get a TextBox object (and its Text property) from the EditingElement property of the DataGridCellEditEndingEventArgs.

By setting

the Cancel property on the DataGridCellEditEndingEventArgs to true, the edit applied by the user will be rejected. Often, an error message (in a dialog box) would be helpful in this situation.
Example markup 4: XAML <Window x:Class="WpfApplication14.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <DataGrid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" CellEditEnding="DataGrid_CellEditEnding" Loaded="DataGrid_Loaded"/> </Grid> </Window> Example method: C# private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { // ... Get the TextBox that was edited. var element = e.EditingElement as TextBox; var text = element.Text; // ... See if the text edit should be canceled. // We cancel if the user typed a question mark. if (text == "?") { // ... Cancel the edit. this.Title = "Invalid"; e.Cancel = true; } else { // ... Show the cell value in the title. this.Title = "You typed: " + text; } }

Scroll.

Many functions of DataGrid can be automated. It even supports scrolling. We use the ScrollIntoView method for this. Please specify the object used as the source for the row (part of the ItemsSource IEnumerable collection).

Here: We add 100 objects to a List, and use that with ItemsSource. We scroll to the final element in the collection (the last row).

Note: Please see the first example on this page for more information about using the ItemsSource property.

Example code: C# using System.Collections.Generic; using System.Windows; using System.Windows.Controls; class Order { public int Size { get; set; } } namespace WpfApplication14 { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void DataGrid_Loaded(object sender, RoutedEventArgs e) { // ... Create Orders. var items = new List<Order>(); for (int i = 0; i < 100; i++) { items.Add(new Order { Size = i }); } // ... Use ItemsSource. var grid = sender as DataGrid; grid.ItemsSource = items; // ... Scroll into view. grid.ScrollIntoView(items[items.Count - 1]); } } }

File.

A DataGrid can be used to edit text files (such as CSV files). This program reads in a text file with the DataGrid_Loaded event. It uses the StreamReader type to read in each line, calls Split, and adds Patient objects to a List.StreamReaderSplit

Then: As the user edits the DataGrid, the List objects are changed. The List is stored in a field on the MainWindow class.

Finally,

the Window_Closing event handler is executed. Here we access the List of Patient objects—this has been modified in memory. We loop over the objects and, with a StreamWriter, persist it to the disk.StreamWriter
File: data.txt Harry,Ford,ABC,1 Sally,Martin,POE,2 Edith,Milner,QED,0 James,Lawry,XYZ,8 Example: XAML <Window x:Class="WpfApplication14.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Closing="Window_Closing"> <Grid> <DataGrid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Loaded="DataGrid_Loaded"/> </Grid> </Window> Example: C# using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Windows; using System.Windows.Controls; class Patient { public string FirstName { get; set; } public string LastName { get; set; } public string Code { get; set; } public int Insurance { get; set; } public Patient(string line) { string[] parts = line.Split(','); this.FirstName = parts[0]; this.LastName = parts[1]; this.Code = parts[2]; this.Insurance = int.Parse(parts[3]); } public string GetLine() { return this.FirstName + "," + this.LastName + "," + this.Code + "," + this.Insurance.ToString(); } } namespace WpfApplication14 { public partial class MainWindow : Window { List<Patient> _list; public MainWindow() { InitializeComponent(); } private void DataGrid_Loaded(object sender, RoutedEventArgs e) { // ... Get data. var patients = new List<Patient>(); using (StreamReader reader = new StreamReader("data.txt")) { while (true) { string line = reader.ReadLine(); if (line == null) { break; } patients.Add(new Patient(line)); } } // ... Set field. this._list = patients; // ... Use ItemsSource. var grid = sender as DataGrid; grid.ItemsSource = patients; } private void Window_Closing(object sender, CancelEventArgs e) { // ... Write the DataGrid at Closing. using (StreamWriter writer = new StreamWriter("data.txt")) { foreach (Patient patient in this._list) { writer.WriteLine(patient.GetLine()); } } } } }

Summary.

DataGrid aids in the presentation, and editing, of tabular data. We adjusted its appearance, used its events, and populated its contents with ItemsSource. It is a powerful, and commonly-needed control in WPF.
Home
Dot Net Perls
© 2007-2019 Sam Allen. All rights reserved. Written by Sam Allen, info@dotnetperls.com.