WPF DataGrid Binding
Published: 2021-02-28 17:21:26

The [WPF](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/?view=netframeworkdesktop-4.8) [DataGrid](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/controls/datagrid?view=netframeworkdesktop-4.8) is the goto grid-like control for desktop development.

**Create the columns first** 

 
```xml
<DataGrid x:Name="processListDataGrid"
          EnableRowVirtualization="True"
          AutoGenerateColumns="False"
          RowDetailsVisibilityMode="VisibleWhenSelected"
 >
    <DataGrid.Columns>
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Button Padding="5">Testing One Two Three</Button>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>


```
The code above says: "For each item in the DataGrid create a Button that has the text shown".

This is the result.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yaclm0lkcius01yc5ym4.png)

These buttons have implicit binding to the Text shown inside the button tag. Similar to innerText in HTML this property is call 'content' instead.

In all of our DataGrid columns we prefer the [DataGridTemplateColumn](https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.datagridtemplatecolumn?view=net-5.0) approach. We do this to take advantage of premade user controls like the [Button](https://docs.microsoft.com/en-us/dotnet/desktop/wpf/controls/button?view=netframeworkdesktop-4.8). The current theme is applied as a result.

**Binding to a Collection of Items**

The data we show, in our case, is that of an [ObservableCollection](https://docs.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.observablecollection-1?view=net-5.0) which is recommended in WPF land.

The binding can be done in the code behind as follows:

```csharp
var content = new ObservableCollection<ProcessInfo>(new ProcessList());
processListDataGrid.ItemsSource = content;

```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hs6o6w80a92spgnh3k7s.png)

By setting the items source directly we are providing the data the grid needs. However, nothing showed until we told each column the property name to show.

```html
 <DataGrid.Columns>
            <DataGridTemplateColumn Width="120">
                <DataGridTemplateColumn.CellTemplate>  
                    <DataTemplate>
                        <Button Tag="{Binding id}" Click="OnKillProcess" HorizontalAlignment="Stretch">Stop Process</Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Style="{DynamicResource gray}" Text="{Binding id}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Style="{DynamicResource gray}"  Text="{Binding windowtitle}"></TextBlock>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock  Style="{DynamicResource gray}" Text="{Binding processname}"></TextBlock>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>

```
For first timers, none of this is intuitive, and even for those returning to WPF there's plenty of stumbling blocks. Keep in mind that our data model defines the fields.

**Data Model**
```csharp
public class ProcessInfo {
    public string id { get; set; }
    public string windowtitle { get; set; }
    public string processname { get; set; }
}

Don't forget the getters and setters!
```

**Where did the data come from?**
```csharp
public class ProcessList : List<ProcessInfo> {
    public ProcessList()        {
        var items = Process.GetProcesses().Where(item => item.MainWindowTitle != string.Empty ||
        item.ProcessName.Contains("chromedriver")).ToList();
        items.ForEach(item =>
        {
            this.Add(new ProcessInfo()
            {
                id = item.Id.ToString(),
                windowtitle = item.MainWindowTitle,
                processname = item.ProcessName,
            });
        });
    }
}

```
Of course, the System.Diagnostics.Process class!

**The Button Click Handler**
```csharp
private async void OnKillProcess(object sender, RoutedEventArgs e)
{
    Button btn = (Button)sender;
    int id = int.Parse(btn.Tag.ToString());
    await Task.Run(() =>
    {
        var proc = Process.GetProcessById(id);
        proc.Kill();
    });
    this.RefreshView();
}

```
Async first to stop any GUI lag.

It's all simple once we know how, it's easily remembered if we log how to do it on Dev.to.

JWP2021 WPF UserControl Process