4

I'm still new to Databinding and have been reading and researching this question for hours now, and I'm hoping someone can at least point me in the right direction.

What I have is a DataTable populated with the objects such as:

public class SimpleObject
{

    public string DisplayValue { get; set; }
    public bool Match { get; set; }
    public string BackGroundColor
    {
        get { if (Match) return "Green"; else return "White"; }
        set { //do nothing }
    }

}

I've set up my headers for the columns of the datatable as such:

DataTable MyDataTable = new DataTable()
List headers = new List<string>() {"Header1", "Header2", "Header3", "Header4"}
foreach (string key in headers)
{         
    MyDataTable.Columns.Add(new DataColumn(key, typeof(SimpleObject)));
}

And populated my DataTable rows by adding rows similar to:

SimpleObject[] rowList = new SimpleObject[4]
DataRow dataRow = MyDataTable.NewRow();
for(int i = 0; i < 4; i++)
{
    //Not really how I determine values, but this will do for a basic example
    rowList[i].DisplayValue = i.ToString();
    rowList[i].Match = i % 2 == 0;
}
dataRow.ItemArray = rowList;
MyDataTable.Rows.Add(dataRow);

SimpleDataGrid.DataContext = MyDataTable;

Now, what I want to do is bind MyDataTable to the DataGrid such that:

  • SimpleObject.DisplayValue is shown in the cell's value
  • the background color of the cell is determined by SimpleObject.BackGroundColor

If anyone could give me advice as to how to this, I would much appreciate it! So far I've tried doing something similar to this:

 <DataGrid Name="SimpleDataGrid" 
                      AutoGenerateColumns="False"
                      ItemsSource="{Binding}">
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="Header1" Width="100">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=Header1.DisplayValue}"
                                           BackGround="{Binding Path=Header1.BackGroundColor}"
                                   />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>

 </DataGrid>

But had no luck. I can't even get the DisplayValue to bind to the Text (even without trying to bind BackGroundColor). Any help or direction would be greatly appreciated!

mario87
  • 291
  • 3
  • 7
  • The `set` for BackgroundColor is an infinite loop, but likely not your problem at hand. – user7116 Nov 28 '12 at 18:24
  • True, I made that object quickly to simplify my real object. Fixed though – mario87 Nov 28 '12 at 18:28
  • I can't test it atm, but I wonder if it would work if your `BackgroundColor` property was of type `Brush` and it returned `Brushes.Green` or `Brushes.White` – vlad Nov 28 '12 at 18:40
  • Well, as is, I am not even getting the text to bind. I guess I should clarify that in the question – mario87 Nov 28 '12 at 18:43
  • I see. I'm pretty sure you don't need `Header1` in the `Path` property; it should be something like `Path=DisplayValue` – vlad Nov 28 '12 at 18:48
  • @vlad, that's not working for me. Without "Header1." how would it know which Datatable value to pull from? – mario87 Nov 28 '12 at 19:27
  • I just tried it, and it seems to work fine for me. Wonder what the difference is.. – Peter Hansen Nov 28 '12 at 19:37
  • @Peter, me as well. Any chance you could show your source code? Or was it just a matter of copy/pasting (fixing syntax errors) of the code above? – mario87 Nov 28 '12 at 19:55
  • More or less just the same you have, with fixed syntax, yes. But I can show the code. – Peter Hansen Nov 28 '12 at 20:03

1 Answers1

1

I have tried replicating your problem, but it seems to work fine for me.

I have added 2 columns to the DataGrid, and the DataTable has 1 item added to it, so 1 row will be created.

The TextBlocks have both the Text and Background properties bound correctly.

Here is the the source code I have used. See if it works for you.

XAML:

<DataGrid Name="SimpleDataGrid" 
                  AutoGenerateColumns="False"
                  ItemsSource="{Binding}">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Header1" Width="100">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=Header1.DisplayValue}"
                               Background="{Binding Path=Header1.BackGroundColor}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Header2" Width="100">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Path=Header2.DisplayValue}"
                               Background="{Binding Path=Header2.BackGroundColor}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

Code-behind:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        DataTable MyDataTable = new DataTable();
        List<string> headers = new List<string>() { "Header1", "Header2", "Header3", "Header4" };

        foreach (string key in headers)
        {         
            MyDataTable.Columns.Add(new DataColumn(key, typeof(SimpleObject)));
        }

        SimpleObject[] rowList = new SimpleObject[4];
        DataRow dataRow = MyDataTable.NewRow();

        for (int i = 0; i < 4; i++)
        {
            //Not really how I determine values, but this will do for a basic example
            rowList[i] = new SimpleObject();
            rowList[i].DisplayValue = i.ToString();
            rowList[i].Match = i % 2 == 0;
        }
        dataRow.ItemArray = rowList;
        MyDataTable.Rows.Add(dataRow);

        SimpleDataGrid.DataContext = MyDataTable;
    }        
}

public class SimpleObject
{
    public string DisplayValue { get; set; }
    public bool Match { get; set; }
    public string BackGroundColor
    {
        get 
        { 
            if (Match) 
                return "Green"; 
            else return "Blue"; 
        }
    }
}
Peter Hansen
  • 8,807
  • 1
  • 36
  • 44
  • This is what I want to do, and this works for me as well. My project is very similar to this code, but will not work. It's just a matter of finding the small difference and fixing it now though, thank you for your help! – mario87 Nov 28 '12 at 20:56