DataGrid
, WPFA 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. We use event handlers and properties to work with DataGrid
in C#.
ItemsSource
This example uses DataGrid
and its ItemsSource
property with a List
. First, create a WPF project and drag a DataGrid
to your window.
Loaded
" to the DataGrid
. In Loaded
, we assign the ItemsSource
property to a List
of objects.class
, there are 2 public properties: Name (a string
) and Size
(an int
).DataGrid
, each property becomes a column header. So it has "Name" and "Size
" columns.ItemsSource
accepts only an IEnumerable
. Many types (like array and List
) implement the IEnumerable
interface
.IEnumerable
(that is used with ItemSource
) uses objects, each object's properties are evaluated.<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>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; } } }
A grid is sometimes hard to read—the rows are hard to follow. The DataGrid
offers the AlternatingRowBackground
attribute to make rows more distinguished in a visual way.
<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
With the SelectedItems
property, we get a List
of selected cells. In this example, we populate the DataGrid
with a List
of objects.
SelectionChanged
event by adding the DataGrid_SelectionChanged
method.SelectionChanged
, we loop over the items in the SelectedItems
List
. And we cast each object to its original type and display it.<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>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.
CellEditEnding
method, we can cancel the edit. This is useful if we detect an invalid entry.TextBox
object (and its Text property) from the EditingElement
property of the DataGridCellEditEndingEventArgs
.DataGridCellEditEndingEventArgs
to true, the edit applied by the user will be rejected.<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>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; } }
Many functions of DataGrid
can be automated. For scrolling, we use the ScrollIntoView
method—specify the object used as the source for the row (part of ItemsSource
).
List
, and use that with ItemsSource
. We scroll to the final element in the collection (the last row).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]); } } }
A DataGrid
can be used to edit text files. This program reads in a text file. Then it uses StreamReader
to read in each line, calls Split
, and adds objects to a List
.
DataGrid
, the List
objects are changed. The List
is stored in a field on the Main
Window class
.Window_Closing
event handler is executed. We loop over the objects and, with a StreamWriter
, persist it to the disk.Harry,Ford,ABC,1 Sally,Martin,POE,2 Edith,Milner,QED,0 James,Lawry,XYZ,8<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>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()); } } } } }
DataGrid
helps in the presentation, and editing, of tabular data. We adjusted its appearance, used its events, and populated its contents with ItemsSource
.