How to dynamically add a converter in code-behind

Grayson Mitchell picture Grayson Mitchell · Feb 22, 2010 · Viewed 20k times · Source

I am Binding a Datagrid to dynamic data via IDictionary: http://www.scottlogic.co.uk/blog/colin/2009/04/binding-a-silverlight-datagrid-to-dynamic-data-via-idictionary/comment-page-1/#comment-8681

But I do not want to define any columns in the xaml (below is how it is done in Colin Eberhardt's post

<data:DataGrid.Columns>
    <data:DataGridTextColumn Header="Forename" Binding="{Binding Converter={StaticResource RowIndexConverter}, ConverterParameter=Forename}" />
</data:DataGrid.Columns>

So I have written the following code to try and do the same thing in the code behind, but the code does not call the RowIndexConverter. Something must be missing.

Code:

// add columns

DataGridTextColumn textColumn = new DataGridTextColumn();
textColumn.Header = "Forename";

Binding bind = new Binding("Forename");
bind.Converter = new RowIndexConverter() ;
bind.ConverterParameter = "Forename";            

textColumn.Binding = bind;
_dataGrid.Columns.Add(textColumn);

Rest of the code (here for context):

// generate some dummy data
Random rand = new Random();
for (int i = 0; i < 200; i++)
{
    Row row = new Row();
    row["Forename"] = s_names[rand.Next(s_names.Length)];
    row["Surname"] = s_surnames[rand.Next(s_surnames.Length)];
    row["Age"] = rand.Next(40) + 10;
    row["Shoesize"] = rand.Next(10) + 5;

    _rows.Add(row);
}

// bind to our DataGrid
_dataGrid.ItemsSource = _rows;    

public class Row
{
    private Dictionary<string, object> _data = new Dictionary<string, object>();

    public object this[string index]
    {
        get
        {
            return _data[index];
        }
        set
        {
            _data[index] = value;
        }
    }
}

Answer

Timores picture Timores · Feb 25, 2010

The converter is called after getting at the data through the property path. As there is no "Forename" property in Row, it does not work (you can see the Binding exception in the Output window).

I solved it by changing the Binding definition to:

    Binding bind = new Binding();
    bind.Mode = BindingMode.OneWay;

as you cannot have two-way binding without a path (the exception I got without the second line). Having no property path makes sense, on second thought, as we want to bind to the full Row object, not to one of its properties.

Note: tested with VS 2008 SP1, WPF project.