Search code examples
wpfdatagriddatatemplate

how to show an object as a row of wpf datagrid and convert it back to be an object


I have an object similar to

class Quote
{
    string Ticker {set; get; }
    string Rating {set; get;}
    People Sender {set; get;}
}

Peaple is defined as,

class People
{
    string Email {set; get;}
    int Age {set; get;}
    string Firm {set; get;}
}

I also have an ObservableCollection of Quote,

ObservableCollection <Quote> QuoteList;

Now I would like to display the QuoteList in a DataGrid, such that each row have the following 3 cells, 1. Quote.Ticker 2. Quote.Rating 3. Quote.Sender.Email

I also would like to, if I click each row, I can get the Quote object of that clicked row. May I ask how can I achieve that?


Solution

  • If you bind your DataGrid to an ItemsSource of an ObservableCollection<Quote> each DataGridRow will be built with the Quote object as it's DataContext (data layer).

    By default, a DataGrid will automatically generate a column for each property on the data item, so in your case it would generate a column for Ticker, Rating, and Sender.

    You can either override that by setting AutoGenerateColumns="False" and defining your own <DataGrid.Columns>, which includes a column bound to Sender.Email

    <DataGrid ItemsSource="{Binding Quotes}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Ticker"  Binding="{Binding Ticker}"/>
            <DataGridTextColumn Header="Rating"  Binding="{Binding Rating}"/>
            <DataGridTextColumn Header="Email"  Binding="{Binding Sender.Email}"/>
        </DataGrid.Columns>
    </DataGrid>
    

    or you can use an implicit DataTemplate to tell WPF to draw the Sender object with a string containing the Email property

    <DataGrid ItemsSource="{Binding Quotes}">
        <DataGrid.Resources>
            <DataTemplate TargetType="{x:Type local:People}">
                <TextBlock Text="{Binding Email}" />
            </DataTemplate>
        </DataGrid.Resources>
    </DataGrid>
    

    Of the two, I'd pick the first one for your situation since you won't need to code anything extra for things like editing

    As for getting the data object when the row is clicked, simply check out the DataContext of the row, or bind your CommandParameter to "{Binding }"