3

我已经DataGridView绑定了DataTable一些数字数据,我需要两件事来确保它们正常工作:

  1. 数字排序 ( doubles/ ints) 对每一列的数字,
  2. 在特殊情况下可以添加一些文本(如“x”或“-”)而不是数字。

有没有一种简单的方法可以在 DataTable 级别添加它们?

我知道我可以将DataTable's 的列类型String更改为绘制等

此外,由于我的 DGV 生成的数量和方式,它不会像为我拥有的每个 DGV 添加一种方法那么简单。

[编辑]

我将同一组 DataTables 编写到 excel 文件中,因此对它们的工作方式进行重大更改将是有问题的并且容易出错 - 我想避免它。

我在大多数情况下填充数据表的代码如下所示:

var row = MyDataTable.GetMyDataTableNewRow();  
row.partName = part.name;  
row.weight = part.weight.ToString();  // it's double  
row.quantity = part.GetParentSet().FindQuantities(part.name).ToString(); // it's int  
row.maxsize = part.CalculateMaxSize().ToString();  
MyDataTable.AddMyDataTableRow(row);
4

2 回答 2

4

在级别定义所需行为的唯一方法DataTable是引入一个包含双精度和字符串的自定义类型,并定义一个适当的TypeConverter(以正确显示对象并在 中启用编辑DataGridView)。

例如:

[TypeConverter(typeof(DoubleOrTextConverter))]
public class DoubleOrText : IComparable
{
    public double Value { get; private set; }
    public string Text { get; private set; }
    public DoubleOrText(double val, string text)
    {
        this.Value = val;
        this.Text = text;
    }
    public static DoubleOrText FromString(System.Globalization.CultureInfo culture, string str)
    {
        double v;
        if (double.TryParse(str, out v))
            return new DoubleOrText(v, null);
        return new DoubleOrText(0, str);
    }
    public string ToString(System.Globalization.CultureInfo culture)
    {
        if (this.Text != null)
            return this.Text;
        return this.Value.ToString(culture);
    }
    // define your sorting strategy here
    public int CompareTo(object obj)
    {
        if (obj == null) return 1;

        var other = obj as DoubleOrText;
        if (other != null)
            return this.Value.CompareTo(other.Value);
        else
            throw new ArgumentException("Object is not a DoubleOrText");
    }
}

public class DoubleOrTextConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
            return true;
        return base.CanConvertFrom(context, sourceType);
    }
    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
            return DoubleOrText.FromString(culture, value as string);
        return base.ConvertFrom(context, culture, value);
    }
    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string))
        {
            var dValue = (DoubleOrText)value;
            return dValue.ToString(culture);
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

使用示例:

DataTable dt = new DataTable();
dt.Columns.Add("Column 1", typeof(DoubleOrText));

dt.Rows.Add(new DoubleOrText(0.0, null));
dt.Rows.Add(new DoubleOrText(1.0, "X"));
dt.Rows.Add(new DoubleOrText(2.3, "-"));
dt.Rows.Add(new DoubleOrText(4.1, null));

this.dataGridView1.DataSource = dt;

结果:

在此处输入图像描述

于 2012-08-08T14:37:38.403 回答
1

使用 ,DataGridView您可以在 UI 级别应用格式,以处理您在不将列更改为文本的情况下专门更改数字列中的某些值的情况。

这是使用 的CellFormattingCellParsing事件来实现的DataGridView

例如,假设您的数据表中有一个 int 列,并且您希望将 1 的所有实例显示为 x,将 3 的所有实例显示为 y。

CellFormatting像这样使用事件:

void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (dataGridView1.Columns[e.ColumnIndex].Name == "CustomerID")
    {
        if (int.Parse(e.Value.ToString()) == 1)
        {
            e.Value = "x";
        }
        else if (int.Parse(e.Value.ToString()) == 3)
        {
            e.Value = "y";
        }
    }
}

使用这种方法,底层数据表和底层单元格值都不会受到影响,因此格式化仍然可以正常工作,就好像你有数字 1 和 3。

然后,您将需要在CellParsing事件中进行一些处理以将字符串转换回来。这又是因为您的基础表仍然有一个数字列。

在被解析的值不转换为 int 的情况下,类似下面的内容只是使用单元格的实际值。但是,您可以在此处理程序中执行您需要的任何操作:

void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
    int parsedValue = 0;
    if (!int.TryParse(e.Value.ToString(), out parsedValue))
    {
        if (int.TryParse(dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString(), out parsedValue))
            e.Value = parsedValue;
        else
            e.Value = 0;

        e.ParsingApplied = true;
    }

} 
于 2012-08-08T16:56:20.117 回答