CustomDataGridViewColumn 与具有自定义排序的 DataGridViewTextBoxColumn

CustomDataGridViewColumn vs DataGridViewTextBoxColumn with custom sort

您好,我目前有一个 DataGridView,其中第一列包含一个人的姓名,直到现在我一直手动将值设置为表示 Person 对象的字符串。其余列包含其他 classes/strings.

我一直在尝试将此人分配给单元格值,以便更容易找到附加到该单元格的人。我将 ToString() 方法添加到我的 Person class 并且一切正常,直到我尝试使用

对列进行排序
_dataGridView.Sort(_dataGridView.Columns[0], ListSortDirection.Ascending);

我收到一个 ArgumentException,指出对象必须是字符串类型(我正在使用文本框列)

我已经尝试实现自己的排序方法,但在将单元格值转换为 Person 时遇到问题(说不能将字符串转换为 person),即使我将 Person 指定为值。

public void _rotaView_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
    {
        Person a = (Person)e.CellValue1;
        Person b = (Person)e.CellValue2;

        e.SortResult = a.CompareTo(b);
        e.Handled = true;
    }

无法将类型 'System.String' 的对象转换为类型 'RotaManagerSolution.Person'。

关于如何将自定义 class 存储在 datagridview 单元格值中并且仍然能够对其进行排序,有什么想法吗?

更新

我已经根据我对您的要求的理解更新了示例代码。

您可以混合使用动态对象和 Sortable BindingList 来实现您的目标。

假设这些是您的实体:

class Company
{
    public string Name { get; set; }
    public Person Contact { get; set; }
    public Address HQAddress { get; set; }
}

class Address
{
    public string City { get; set; }
    public string Country { get; set; }
}

// Define other methods and classes here
class Person
{
   public string Name { get; set; }
   public DateTime DOB { get; set; }
   public int Height { get; set; }
   public float Weight { get; set; }
}

这是您的数据:

Person p1 = new Person() { Name = "Hari", DOB = new DateTime(1781, 4, 3), Height = 165, Weight = 60.0f};
Person p2 = new Person() { Name = "Nil", DOB = new DateTime(1781, 4, 3), Height = 165, Weight = 60.0f};

Company c = new Company()
{
    Name = "Sahaj Technologies",
    Contact = p1,
    HQAddress = new Address() { City = "Sarang", Country = "India" }
};

然后您可以使用以下代码来填充您的网格。请注意,它正在使用来自不同实体的数据。事实上,由于使用了动态对象,所以你的数据来自哪里并不重要。

dgv.DataSource = GetSortableBindingList(
    new[] {
        new { CompanyName = c.Name, ContactPerson = c.Contact.Name, HQ = c.HQAddress.City + ", " + c.HQAddress.Country},
        new { CompanyName = "Akshar Inc.", ContactPerson = p2.Name, HQ = "LA, USA"}
    }
);
// Wrapper method to allow dynamic objects
public object GetSortableBindingList<T>(IEnumerable<T> collection) where T : class
{
    return new ObservableCollection<T>(collection).ToBindingList();
}

这是工作演示的 link: http://share.linqpad.net/5257ki.linq

P.S。要 运行 此演示,您需要执行以下步骤:

  1. 下载LINQPad.
  2. 获得EntityFramework.dll。按照显示的说明进行操作 here or here
  3. 解压 LINQPad,将 EntityFramework.dll 复制到与 LINQPad.exe
  4. 相同的文件夹中
  5. 下载 demo 文件,用 LINQPad 打开它并按 F5。

我发现我的问题的解决方案是通过执行以下操作将自定义可排序列表数据绑定到 DataGridView

创建第一列,将数据 属性 设置为 Person class

Name 属性
// Add column for names (people and shifts)
DataGridViewColumn names = new DataGridViewTextBoxColumn();
names.DataPropertyName = "Name";
names.DefaultCellStyle.BackColor = System.Drawing.Color.Azure;
names.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
names.SortMode = DataGridViewColumnSortMode.NotSortable;
_rotaView.Columns.Add(names);

然后添加了这个找到的自定义可排序绑定列表 here

绑定数据

 SortableBindingList<Person> sblist = new SortableBindingList<Person>();

 foreach (Person p in _mainManager.ListOfPeople)
 {
     sblist.Add(p);
 }
 _rotaView.DataSource = sblist;

这样我就可以调用这一行来对列表进行排序

_rotaView.Sort(_rotaView.Columns[0], System.ComponentModel.ListSortDirection.Ascending);