开发者

How to sort DataGridView when bound to a binding source that is linked to an EF4 Entity

开发者 https://www.devze.com 2023-01-31 03:58 出处:网络
I have a DataGridView that is linked t开发者_开发问答o a BindingSource. My BindingSource is linked to an IQueryable list of entities:

I have a DataGridView that is linked t开发者_开发问答o a BindingSource.

My BindingSource is linked to an IQueryable list of entities:

    public void BindTo(IQueryable elements)
    {
        BindingSource source = new BindingSource();
        source.DataSource = elements;

        bindingNavigator1.BindingSource = source;
        dataGridView1.DataSource = source;

    }

I am wanting my users to be able to click on the grid headers to sort the data - struggling to get this to work. Is it possible? If so, how do I do it?


I recently struggled with this same issue; it seems that the IQueryable interface doesn't provide enough information for the DataViewGrid to know how to sort the data automatically; so you have to either repackage your collection from the Entity source using something it can use or do what I did and handle the sorting functionality manually:

      private void myDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
  {
     DataGridViewColumn column = myDataGridView.Columns[e.ColumnIndex];

     _isSortAscending = (_sortColumn == null || _isSortAscending == false);

     string direction = _isSortAscending ? "ASC" : "DESC";

     myBindingSource.DataSource = _context.MyEntities.OrderBy(
        string.Format("it.{0} {1}", column.DataPropertyName, direction)).ToList();

     if (_sortColumn != null) _sortColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
     column.HeaderCell.SortGlyphDirection = _isSortAscending ? SortOrder.Ascending : SortOrder.Descending;
     _sortColumn = column;
  }

I hope that helps.


VB.NET

If you are using a bindingsource with linq syntax you can sort your data like this

In this case When loading a bindningsource associated with a datagridview from entity framwork objects "NCFile" with having a foreign column to a list of "NCFilePartSet "

bsFileSections.DataSource = From ncfps In NCFile.NCFilePartSet Order By ncfps.Sort Select ncfps 

or like this

bsFileSections.DataSource = NCFile.NCFilePartSet.OrderBy(Function(ncfps) ncfps.Sort)

where "Sort" is a column in NCFilePartSet

Updates on entities continue working and reflects back to the database


Yes, it is possible to easily have a sortable DGV when bound to EF data. Use the BindingListView from the BLW library (also, check out How do I implement automatic sorting of DataGridView?).

public void BindTo(IQueryable elements)
{
    BindingSource source = new BindingSource();
    source.DataSource = new BindingListView(elements.ToList());

    bindingNavigator1.BindingSource = source;
    dataGridView1.DataSource = source;

}

In my tests, even when .ToList() was called within the constructor (as above), changes were propagated to the DB, which surprised me.


This code snippet works very well, and fast enough for most purposes...

int iColNumber = 3; //e.g., sorting on the 3rd column of the DGV

MyBindingSource.DataSource = MyBindingList.OrderByDescending(o => o.GetType().GetProperty(MyDataGridView.Columns[iColNumber].Name).GetValue(o));


I suggest you to dynamically convert entities into data table. There is a method

 public static DataTable GetTableFromList<T>(IEnumerable<T> list)
    {
        DataTable dt = new DataTable();
        PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (PropertyInfo property in properties)
            dt.Columns.Add(property.Name, property.PropertyType);

        foreach (T item in list)
        {
            DataRow newRow = dt.NewRow();
            foreach (PropertyInfo property in properties)
            {
                newRow[property.Name] = property.GetValue(item);
            }
                dt.Rows.Add(newRow);
        }

        return dt;
    }

After conversion pass table into bindingsource

source.DataSource = GetTableFromList<T>(elements);

Be aware of property types that cannot be converted into a column types.


maybe this will help you.

internal class CustomDataGridView : DataGridView
{   
    public SortOrder MySortOrder { get; set; }
    protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
    {
        BindingSource MyBindingSource = (BindingSource)base.DataSource;
        DataTable MyDataTable = (DataTable)MyBindingSource.DataSource;
        switch (MySortOrder)
        {
            case SortOrder.None:
                MyDataTable.DefaultView.Sort = base.Columns[e.ColumnIndex].Name + " ASC";
                MyDataTable = MyDataTable.DefaultView.ToTable();
                MyBindingSource.DataSource = MyDataTable;
                MySortOrder = SortOrder.Ascending;
                break;

            case SortOrder.Ascending:
                MyDataTable.DefaultView.Sort = base.Columns[e.ColumnIndex].Name + " DESC";
                MyDataTable = MyDataTable.DefaultView.ToTable();
                MyBindingSource.DataSource = MyDataTable;
                MySortOrder = SortOrder.Descending;
                break;

            case SortOrder.Descending:
                MyDataTable.DefaultView.Sort = Properties.Settings.Default.OderDataGridView; //SqlOriginOrder
                MyDataTable = MyDataTable.DefaultView.ToTable();
                MyBindingSource.DataSource = MyDataTable;
                MySortOrder = SortOrder.None;
                break;
        }
        base.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = MySortOrder; //mini arrow 
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消