Сортировка форматированных значений для DataGridView с привязкой к контексту Entity Framework

Предположим, у меня есть две сущности (весь приведенный ниже код упрощен, чтобы отразить только суть проблемы):

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 (Code-First):

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

И, наконец, я выполняю форматирование для столбца Value в соответствии с FieldType:

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. Я не могу реализовать IComparer в классе FieldValue, потому что мне нужно отсортировать отформатированные значения (не оригинальный байтовый массив).

Моя цель - выполнить сортировку по форматированным значениям в столбце " Значение". Как я могу это сделать?

1 ответ

Решение

Наконец я сделал это с событием 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;
    }
Другие вопросы по тегам