具有界面类型的 DataGridView 单元格不显示值

问题描述 投票:0回答:1

我有一个 DataGridView 可以正常工作,显示数据如下:

private DataGridView dgv;
private List<Item> Items = new();
Items.Add(new() {ID = 1, Service = new() { Name = "Item 1"}, Quantity = 2});
dgv.DataSource = Items;

// [...]

Public Class Item 
{
    public int ID {get; set;}
    public Service Service {get; set;}
    public int Quantity {get; set;}
}

Public Class Service
{
    public string Name {get; set;}
    Public overrides string To string  => Name;
}

在我介绍之前一切都工作得很好

public interface IService 
{
    public string Name {get; set;}
}

然后改变:

public Service Service {get; set;}

致:

public IService Service {get; set;}

然后让

Service
类实现该接口:

public class Service: IService...

一切仍然有效,除了 DataGridView 中的

Service
列什么都不显示,尽管当我用鼠标悬停在它上面时我可以看到值

c# winforms datagridview
1个回答
0
投票

当 DataGridView 需要格式化 Cell 的值以进行演示时,它会对底层 Type 执行一系列(长)测试。
然后,它调用类型的默认格式化程序,因此您可以覆盖类对象中的

ToString()
,以返回格式化值。

当底层类型是接口时,它会验证是否实现了IFormattable。如果不是,那么

FormattedValue
就是
null

另请参阅此处的注释:
DataGridView HeaderCell 为数字类型时不显示值


鉴于当前的结构:

public class Item {
    public int ID { get; set; }
    public IService? Service { get; set; } = null;
    public int Quantity { get; set; }
}

public class Service : IService {
    public string Name { get; set; } = string.Empty;
    public override string ToString() => Name;
}

public interface IService {
    string Name { get; set; }
}

您可以做几件事:

如果需要保持类的结构不变,则处理 CellFormatting 事件并将 Cell 的 Value 设置为当前

e.Value
Service
对象),转换为字符串,即
e.Value.ToString()
:

private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) {
    var dgv = sender as DataGridView;
    if (dgv?.Columns[e.ColumnIndex].Name == nameof(Service)) {
        e.Value = e.Value?.ToString();
    }

    // Or...
    if (e.Value?.GetType() == typeof(Service)) {
        e.Value = e.Value?.ToString();
    }
}

如果您可以更改 Service 类,则实现 IFormattable。如果不需要其他格式(例如,您需要考虑特定的文化或格式),您可以使其

ToString()
实现仅调用现有的
ToString()
覆盖:

public class Service : IService, IFormattable {
    public string Name { get; set; } = string.Empty;
    public override string ToString() => Name;
    public string ToString(string? format, IFormatProvider? provider) => ToString();
}

在这种情况下,您不需要处理

CellFormatting

当然,要使 DataGridView 使用 IFormattable 方法,您需要提供一种格式。因此,在设置 DataGridView 的数据源后,将 Service 列的
Format
属性设置为通用格式,例如:

dgv.Columns["Service"].DefaultCellStyle.Format = "G";

DataGridView 会检查类对象是否实现了 IFormattable,如果实现则调用其方法。

© www.soinside.com 2019 - 2024. All rights reserved.