Question

Im using a datagrid filling the itemsSource by reflection (methodDefinition.Invoke(..)) the target method returns an IQueryable< T > wich T is an EntityType known at runtime.

Since the return type is IQueryable< T >, and IQueryable< T > implements IEnumerable when I do this:

dataGrid1.ItemsSource = methodQuery.Invoke(instance, parameters) as IEnumerable<object>;

Im able to SEE the rows and columns (plus the AutoGeneratingColumns event is thrown, so i can manage the columns) but im unable to sort the rows by clicking on its header.

Then I tried to do this:

dataGrid1.ItemsSource = methodQuery.Invoke(instance, parameters) as List<object>;

But as I expected, an exception is thrown saying that I cannot directly cast the generic type from "Model.Tab_001" to "object".

Also, i tried to convert the result to List< T > at runtime (by the extension of IEnumerable.ToList(), creating an delegate that implements the func to convert the source to List< T >) but since T is only known at runtime and an object (that returns from methodDefinition.invoke) cannot use the extension .ToList() without the explicit declaration of the type T before using this method.

@edit: When I use this method with the same IEnumerable< object > (that is working on datagrid) and to the ToList() extension method, the datagrid is getting filled with blank lines plus Its not firing the AutoGeneratingColumns. So im unable to see the result, just a dataGrid full of blank lines.

Also tried to convert the result to ObservableCollection, reaching the same problem with the List.

Is there a diferent way to sort the rows of the datagrid by clicking on the column header beside using an List as the ItemsSoure of the datagrid?

Was it helpful?

Solution 2

I found an easier way to do it.

Instead of setting the dataGrid to AutoGenerateColumns, i set a property notifier to ItemsSource of the dataGrid, then fill it with a direct cast to IEnumerable< object > then used the ToList() extension.

Whenever my datasource is changed, im adding the columns manually, with its proper headers and bindings.

Now Im able to sort the rows by clicking on the column header.

Code:

...
dataGrid1.ItemsSource = (IEnumerable<object>)methodQuery.Invoke(instance, parameters).ToList();
...

...

private void DataGridItemsSourceChanged(object sender, EventArgs e)
{
        var currentDataGrid =  (DataGrid)sender;

        foreach (TSpe_Reg reg in tabItemSourceChange.TSpe_Reg) // tabItemSourceChange is used to check the table and field names, since im using reflection.
        {
            string headerName = "";
            if (reg.a_short_name != "")
                headerName = reg.a_short_name;
            else
                headerName = reg.a_full_name;
            string boundColumn = "a_" + reg.a_field_name + "_" + tabItemSourceChange.a_table_name;
            DataGridTextColumn ColumnDataGrid = new DataGridTextColumn { Header = headerName, Binding = new Binding(boundColumn) };

        }
}


// Calls the DataGridItemsSourceChanged whenever the DependencyProperty ItemsSource is changed.
private void CallItemSourcePropertyDescriptor(DataGrid currentDataGrid)
    {
        var dpd = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(DataGrid));
        if (dpd != null)
        {
            dpd.AddValueChanged(currentDataGrid, DataGridItemsSourceChanged);
        }
    }

OTHER TIPS

Why not cast first, then convert?

var ienum = (IEnumerable<object>)methodQuery.Invoke(instance, parameters);
dataGrid1.ItemsSource = ienum.ToList();

(Also only use as if you are checking for null afterwards)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top