通过单击带有AutoGenerated列和IEnumerable ItemsSource的列标题DataGrid对行进行排序

时间:2013-08-16 18:16:50

标签: wpf sorting reflection datagrid itemssource

我使用通过反射填充itemsSource的datagrid(methodDefinition.Invoke(..)),目标方法返回IQueryable< T> T是在运行时已知的EntityType。

由于返回类型是IQueryable< T>和IQueryable< T>当我这样做时实现IEnumerable:

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

我能够查看行和列(加上AutoGeneratingColumns事件被抛出,因此我可以管理列)但我无法通过单击其标题对行进行排序。

然后我试着这样做:

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

但正如我所料,抛出一个异常,说我不能直接将泛型类型从“Model.Tab_001”转换为“object”。

另外,我试图将结果转换为List&lt; T>在运行时(通过IEnumerable.ToList()的扩展,创建一个实现func以将源转换为List&lt; T&gt;)的委托,但由于T仅在运行时已知并且是一个对象(从methodDefinition.invoke返回)在使用此方法之前,不能使用扩展名.ToList()而不使用类型T的显式声明。

@edit: 当我使用这个方法与相同的IEnumerable&lt;对象&gt; (正在处理数据网格)和ToList()扩展方法,数据网格填充空白行加上它不触发AutoGeneratingColumns。所以我无法看到结果,只是一个充满空白行的dataGrid。

还试图将结果转换为ObservableCollection,与List达到同样的问题。

是否有不同的方法通过单击使用List作为datagrid的ItemsSoure旁边的列标题对数据网格的行进行排序?

2 个答案:

答案 0 :(得分:0)

为什么不先施放,然后转换?

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

(如果您之后检查as

,也只能使用null

答案 1 :(得分:0)

我找到了一种更简单的方法。

我没有将dataGrid设置为AutoGenerateColumns,而是将属性通知程序设置为dataGrid的ItemsSource,然后使用直接强制转换为IEnumerable&lt;对象&gt;然后使用ToList()扩展名。

每当我的数据源发生变化时,我都会手动添加列,并使用正确的标题和绑定。

现在我可以通过单击列标题对行进行排序。

代码:

...
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);
        }
    }