This is a migrated thread and some comments may be shown as answers.

Dynamic Columns - Adding columns at runtime

4 Answers 316 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Guga
Top achievements
Rank 1
Guga asked on 23 Oct 2012, 06:56 AM
Hi,

I have used the information on this thread:

http://blogs.telerik.com/vladimirenchev/posts/11-09-28/dynamic-binding-for-your-silverlight-applications.aspx

to create a gridview that is bound to an ObservableCollection<DataRow> (DataRow is the same class as in Vladimir's example..).

All works fine (thank you Vladimir) and the grid has a column per each of the properties added to the dictionary inside the DataRow.

My issue is that i need to add additional fields at run time. Something like this:

foreach(var obj in dataRows)
{
    obj["New Field"]=value;
}
where dataRows would be my ObservableCollection<DataRow>.

When I do this I would need to force the gridview to add the new column and reload the rows to show the new values.

Any idea how to do this without having to recreate the gridview object?

Another issue is how to create bidirectional binding for the values in this situation...


Thanks for your help in advance.

4 Answers, 1 is accepted

Sort by
0
Nick
Telerik team
answered on 24 Oct 2012, 10:39 AM
Hello Hugo,

You can add columns on the fly, by using the GridView Columns collection. 

As to how to create bidirectional binding, have you tried binding to the DefaultView instead of the DataTable itself? 

Hope this helps! 

Regards,
Nik
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Guga
Top achievements
Rank 1
answered on 24 Oct 2012, 10:28 PM
Hi Nik,

Thanks for replying.

I am sory I was not clear enough on my post.

I know I can manually add/remove columns to the database, but I was trying to do it automatically with either the AutoGenerateColumns = true (this is the one I tried to implement) or with an ObservableCollection of columns (this would be another option, where I would need to create a behaviour that would change the Columns collection of the grid view when the ObservableCollection would change. I have not tried this.).

To make it clear I have the code working at the moment with a manual add/remove columns process when the user needs to add/remove a column, but this is a clear breach of the separation of concerns between the presentation layer and the controller (ViewModel or whatever other pattern you are implementing) layer.

Regarding the directional binding the only way I got it to work was with a manual handling of the CellEditEnded event like this:

private void AnalysesDataGrid_CellEdit_Ended(object sender, GridViewCellEditEndedEventArgs e)
        {
            string columnName = (string)e.Cell.Column.Header;
            DataRow row = e.Cell.ParentRow.Item as DataRow;
            row[columnName] = e.NewData;
 
(...)

Even uglier code...

This is the code I have at the moment to generate the columns manually:

GridViewCheckBoxColumn column = new GridViewCheckBoxColumn();
 
column.Header = chem.Analysis;
 
Binding b = new Binding("");
b.Converter = new DataRowColumnToValueConverter();
b.ConverterParameter = chem.Analysis;
 
b.Mode = BindingMode.TwoWay;
 
column.DataMemberBinding = b;
column.AutoSelectOnEdit = true;
column.EditTriggers = Telerik.Windows.Controls.GridView.GridViewEditTriggers.CellClick;
 
this.dgAnalyses.Columns.Add(column);

This is the Converter code:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    DataRow row = value as DataRow;
    string columnName = parameter as string;
 
    if (row != null & columnName != null)
    {
        return row[columnName];
    }
 
    return null;
}



I have tried to create the binding with both:

Binding b = new Binding(chem.Analysis) -> Works great for getting the value but throws an exception when trying to set it stating that the DataRow does not have the property with whatever the ColumnName is, which is expected since silverlight does not support binding to dynamic properties of dynamic objects.

Binding b= new Binding("[" + chem.Analyses + "]") -> This has the potencial to work but I am screwing this up. I know you can force the binding to be done with indexed properties like DataRow[index], I am just not sure how to set it in c#. Any ideas?


I hope that was a bit clearer. :)
0
Nick
Telerik team
answered on 25 Oct 2012, 09:11 AM
Hi Hugo,

You can find a sample "Binding" Behavior for the GridView Columns in your local copy of our examples

As to the Biding, again the suggested approach is to bind to the DefaultView of the DataTable instead of the Table itself.

Let me know if you need any further help with this! 

All the best,
Nik
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Guga
Top achievements
Rank 1
answered on 25 Oct 2012, 10:40 PM
Hi Nik,

Thank you for the binding behavior example. I will give a try when I get a chance.

Cheers,

Hugo
Tags
GridView
Asked by
Guga
Top achievements
Rank 1
Answers by
Nick
Telerik team
Guga
Top achievements
Rank 1
Share this question
or