Search code examples
c#wpfdatagridrowmanual

How to bind Fields to DataGrid in WPF?


I am programming UI with WPF for a month. So i am new in this world. This is my first ever post here and my motherlanguage isn't English. So if there is any mistake in my writing, sorry for that.

I have a problem with WPF and I am not able to find a solution for it. I am trying to make completely customizable DataGrid in WPF and I don't want the DataGrid to create columns or rows automatically. I have an ObservableCollection named Sinif_Tutucu (means Class_Holder in my motherlanguage) which holds classes. These classes have the same Field and Properties, but their values are different. I am creating the columns one by one according to Fields and Properties in these classes. After this I am adding columns to DataGrid manually.

Then I am adding the rows with ItemsSource like this.

DataGrid_1.ItemsSource = Sinif_Tutucu;

This populates only properties in the DataGrid and columns made up of fields remain empty. I have searched this and i guess there is no way to bind Fields to DataGrid. Classes within Sinif_Tutucu have thousands of fields. So I can't turn fields to properties and I don't want to code the whole datagrid structure from scratch. Because WPF DataGrid structure offers many useful features which i am currently using. I am able to get Field names and their values or Property names and values. I just need to create each row myself (like columns) and populate their cells one by one with my hand with C#. Or somehow I need to convert these Fields to Properties programmatically. Is there any way to achieve this?


Solution

  • Supposing your class that you want to show in the datagrid looks like this

    public class Data
    {
        public int Value;
        public string Name;
        public DateTime Date = DateTime.Now;
    }
    

    Because you cannot bind fields to DataGridColumns, you have to dynamically create the columns and the records. Here is a short snippet which you can use to do that. This method creates new dynamic objects in a List, which stores the same data as in your ObservableCollection. This List is set as the new ItemSource of your DataGrid. This snippet only creates DataGridTextColumns. You migth have to modify this solution, if want to use other DataGridColumns.

    private void loadDataGrid()
    {
        List<dynamic> dataObjects = new List<dynamic>();
        dynamic dataObject;
        IDictionary<string, object> dataObjectValues;
    
        var fields = typeof(Data).GetFields();
    
        foreach (var item in Sinif_Tutucu)
        {
            dataObject = new System.Dynamic.ExpandoObject();
    
            foreach (var field in fields)
            {
                dataObjectValues = (IDictionary<string, object>)dataObject;
                dataObjectValues[field.Name] = field.GetValue(item);
            }
    
            dataObjects.Add(dataObject);
        }
    
        dataObjectValues = (IDictionary<string, object>)dataObjects[0];
    
        foreach (var pair in dataObjectValues)
        {
            var binding = new Binding(pair.Key);
    
            DataGridTextColumn col = new DataGridTextColumn() { Binding = binding, Header = pair.Key }; //You might want to use another DataGridColumn-Type
    
            dataGrid.Columns.Add(col);
        }
    
        dataGrid.ItemsSource = dataObjects;
    }