简体   繁体   English

绑定到Entity Framework上下文的DataGridView的格式化值排序

[英]Formatted values sorting for DataGridView with binding to Entity Framework context

Suppose I have two entities (all code all below is simplified to reflect only the core of the problem): 假设我有两个实体(下面的所有代码都经过简化以仅反映问题的核心):

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

and I use them in EF DbContext (Code-First approach): 我在EF DbContext(代码优先方法)中使用它们:

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

I use databinding to WinForms DataGridView (according to this msdn article ) 我对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();                   
    }

And finally I perform formating for Value column according to FieldType : 最后,我根据FieldTypeValue列执行格式化:

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

My problem is that user sorting (by column header clicking) for Value column in DataGridView is not working out-of-the-box ( SortMode is set to Automatic of course). 我的问题是,对DataGridView中的“ 值”列的用户排序(通过单击列标题)不是开箱即用的(当然,“ 排序模式”设置为“ 自动 ”)。 Moreover: 此外:

  1. I can't use SortCompare event and Sort function for DataGridView because DataSource is set. 因为设置了数据源 ,所以我无法对DataGridView使用SortCompare事件和Sort函数。
  2. I can't implement IComparer in FieldValue class because I need to sort formatted values (not original byte array). 我无法在FieldValue类中实现IComparer ,因为我需要对格式化的值(而不是原始字节数组)进行排序。

My goal is to perform sorting according to formatted values in Value column. 我的目标是根据“ 值”列中的格式化值进行排序。 How can I do that? 我怎样才能做到这一点?

Finally I've done it with ColumnHeaderMouseClick event and dynamic BindingSource changing (info was taken from comments to this question ) 最后,我通过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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM