0

TL;DR: if a DataGrid cell is bound to a specific object (not string, int, ...), how can I access it in converter or setter?

Full version:

I have a DataGrid that is bound to a DataTable:

<Window x:Class="TabControlTests.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="grid" ItemsSource="{Binding Data}" />
    </Grid>
</Window>

DataTable is generated dynamically (and in real life code I don't know the column names):

public partial class MainWindow : Window
{
    public DataTable Data { get; set; }

    public MainWindow()
    {
        InitializeComponent();

        DataContext = this;

        SetDataTable();
    }

    private void SetDataTable()
    {
        var dt = new DataTable();

        var name = new DataColumn("Name", typeof(object));
        var age = new DataColumn("Age", typeof(int));
        var home = new DataColumn("Home", typeof(string));
        dt.Columns.Add(name);
        dt.Columns.Add(age);
        dt.Columns.Add(home);

        AddRow(dt, "Kavitha Reddy", 15, "NY");
        AddRow(dt, "Kiran Reddy", 24, "LA");
        AddRow(dt, "John Doe", 55, "TX");

        Data = dt;
    }

    private void AddRow(DataTable dt, string name, int age, string home)
    {
        var dr = dt.NewRow();
        dr["Name"] = new Person(name, age >= 18);
        dr["Age"] = age;
        dr["Home"] = home;
        dt.Rows.Add(dr);
    }
}

}

Note that for Name column I assign an object, not string. As it has ToString() method implemented it displays the name:

public class Person
{
    public string Name { get; set; }
    public bool IsAdult { get; set; }

    public Person(string name, bool isAdult)
    {
        Name = name;
        IsAdult = isAdult;
    }

    public override string ToString()
    {
        return Name;
    }
}

How can I display a different background in the Name column for each person that has IsAdult == false? I tried to use some converters but I cannot access the Person object anywhere, all I got was DataGridCell instance.

EDIT

This is how I tried to use a converter:

<Window.Resources>
    <local:ValueToBrushConverter x:Key="ValueToBrushConverter" />
    <Style x:Key="CellStyle" TargetType="DataGridCell">
        <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource ValueToBrushConverter}}" />
    </Style>
</Window.Resources>
<Grid>
    <DataGrid x:Name="grid" ItemsSource="{Binding Data}" CellStyle="{StaticResource CellStyle}" />
</Grid>
bpiec
  • 1,561
  • 3
  • 23
  • 38
  • Where and how are you trying to use a converter? – mm8 Jun 22 '17 at 13:04
  • See the updated question. – bpiec Jun 22 '17 at 13:08
  • *"changing to `object` does not change anything, I still get DataGridCell"* communicates nothing to me. The code in my answer was tested and worked perfectly. If you're unable to generalize it to a similar problem, or if your actual problem bears no resemblance to the code you posted, I can't help you. You can't do this with autogenerated columns. Good luck. – 15ee8f99-57ff-4f92-890c-b56153 Jun 22 '17 at 13:16
  • Why are you using a mixing a DataTable with custom User objects? This is not a good idea. – mm8 Jun 22 '17 at 13:17
  • Are you saying that `DataGridCell` is the type of the `value` your converter is getting? What else did you expect? Look at its `DataContext`. – 15ee8f99-57ff-4f92-890c-b56153 Jun 22 '17 at 13:18
  • 2
    `DataContext = this;`... Please learn MVVM. `Value="{Binding Converter={StaticResource ValueToBrushConverter}}"` is not a solution? – Maxim Jun 22 '17 at 13:19

1 Answers1

2

You can't really store the Person object in the DataRow. You can confirm this yourself:

var dr = dt.NewRow();
//set the Name column to a Person object
dr["Name"] = new Person(name, age >= 18);
//...and retrieve it. It is now a string:    
var thePerson = dr["Name"] as string;

Mixing an object model with a DataTable is not a good idea. You should replace the DataTable with a collection of custom objects. Then you will be able to use a value converter or a DataTrigger to set the Background property of the cell.

mm8
  • 163,881
  • 10
  • 57
  • 88