绑定到实体框架上下文的DataGridView的格式化值排序

本文关键字:DataGridView 格式化 排序 上下文 实体 框架 绑定 | 更新日期: 2023-09-27 18:10:17

假设我有两个实体(下面所有的代码都简化了,只反映了问题的核心):

public class TemplateField
{
    public Guid Id { get; set; }
    public String Name { get; set; }
    public String FieldType { get; set; }        
}
public class FieldValue
{
    public Guid Id { get; set; }
    public Guid TemplateFieldId { get; set; }
    public Byte[] Value { get; set; }        
}

,我在EF DbContext(代码优先方法)中使用它们:

public class MyContext : DbContext
{
    public DbSet<TemplateField> TemplateFields { get; set; }
    public DbSet<FieldValue> FieldValues { get; set; }
}

我使用数据绑定到WinForms DataGridView(根据这个msdn文章)

private void LoadAndBindEntities()
    {
    // Call the Load method to get the data for the given DbSet 
        // from the database. 
        // The data is materialized as entities. The entities are managed by 
        // the DbContext instance. 
        _context.FieldValues.Load();                   
        _context.TemplateFields.Load();             

        // Bind the categoryBindingSource.DataSource to 
        // all the Unchanged, Modified and Added Category objects that 
        // are currently tracked by the DbContext.
        // Note that we need to call ToBindingList() on the 
        // ObservableCollection<TEntity> returned by
        // the DbSet.Local property to get the BindingList<T>
        // in order to facilitate two-way binding in WinForms.
        fieldValuesBindingSource.DataSource = _context.FieldValues.Local.ToBindingList();
        templateFieldsBindingSource.DataSource = _context.TemplateFields.Local.ToBindingList();                   
    }
最后根据FieldType: 对Value列进行格式化
private void DataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
    ............
    e.Value = GetFormattedValue(e.Value as byte[], templateFieldId);
    ............                          
    }
internal object GetFormattedValue(byte[] value, Guid templateFieldId)
    {
        ............
        //Getting FieldType for templateFieldId
        ............
        if (value == null)
            return ("NULL");
        else
        {
            if (type == typeof(String))
                return (Encoding.Unicode.GetString(value));
            else if (type == typeof(DateTime))
                return (DateTime.FromBinary(BitConverter.ToInt64(value, 0)));
            else if (type == typeof(Boolean))
                return (BitConverter.ToBoolean(value, 0));
            else if (type == typeof(Int32))
                return (BitConverter.ToInt32(value, 0));
            else if (type == typeof(Double))
                return (BitConverter.ToDouble(value, 0));
            else
                return ("unknown field type: " + type.Name);
        }
    }

我的问题是,用户排序(通过列标题点击)为列在DataGridView不工作开箱即用(SortMode设置为自动当然)。此外:

  1. 我不能使用SortCompare事件和Sort函数DataGridView,因为设置了DataSource
  2. 我不能实现IComparerFieldValue类因为我需要排序格式化的值(不是原始字节数组)。

我的目标是根据Value列中的格式化值执行排序。我该怎么做呢?

绑定到实体框架上下文的DataGridView的格式化值排序

最后我用ColumnHeaderMouseClick事件和动态BindingSource更改(信息是从评论中获取的这个问题)

private void DataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        //clicked column with formatted values
        if (e.ColumnIndex == formattedValueColumnIndex)
        {
            // Sort this column for the first time
            if (direction == SortOrder.None)
            {
                // Remove the SortGlyph for all columns
                foreach (DataGridViewColumn column in DataGridView.Columns)
                    column.HeaderCell.SortGlyphDirection = SortOrder.None;
                direction = SortOrder.Ascending;
            }
            else
                // Sort the same column again, reversing the SortOrder for it
                direction = direction ==
                            SortOrder.Ascending
                                ? SortOrder.Descending
                                : SortOrder.Ascending;
                            if (direction == SortOrder.Ascending)
                fieldValuesBindingSource.DataSource = new BindingList
                    <FieldValue>(
                    _context.FieldValues.Local.OrderBy(
                        item => GetFormattedValue(item.Value, item.TemplateFieldId).ToString())
                            .ToList());
            else
                fieldValuesBindingSource.DataSource = new BindingList
                    <FieldValue>(
                    _context.FieldValues.Local.OrderByDescending(
                        item => GetFormattedValue(item.Value, item.TemplateFieldId).ToString())
                            .ToList());
        }
        //clicked column with ordinary (not-formatted) value
        else
            //and column with formatted value was sorted before the click
            if (direction != SortOrder.None)
            {
                direction = SortOrder.None;
                fieldValuesBindingSource.DataSource =
                    _context.FieldValues.Local.ToBindingList();
            }
    }

    void DataGridView_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        //clicked column with formatted value - changing SortGlyph for it
        if (DataGridView.Columns[formattedValueColumnIndex].HeaderCell.SortGlyphDirection != direction)
            logBookFieldValueDataGridView.Columns[formattedValueColumnIndex].HeaderCell.SortGlyphDirection = direction;
    }