c#DataGridView绑定到DataTable - 如何将字符添加到双列中?

时间:2012-08-08 14:13:51

标签: c# sorting datagridview datatable

我已将DataGridView绑定到DataTable并附带一些数字数据,我需要两件事来确保正常工作:

  1. 每个包含数字的列的数字排序(doubles / ints
  2. 在特殊情况下可以添加一些文本(例如“x”或“ - ”)而不是数字。
  3. 有没有一种简单的方法可以在DataTable级别添加它们?

    我知道我可以将DataTable列的类型更改为String,但之后我需要添加更多代码,只是为了按已经内置的方式对列进行排序 - 我当然不需要改变绘制字形的方式等。

    另外,由于我的DGV产生的数量和方式,它不会像为每个DGV添加一种方法那么容易。

    [编辑]

    我将同一组DataTables写入excel文件,因此对其工作方式的重大改变会产生问题且容易出错 - 我想避免使用它。

    我在大多数情况下填写dataTables的代码如下所示:

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

2 个答案:

答案 0 :(得分:4)

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

e.g。 :

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

结果:

enter image description here

答案 1 :(得分:1)

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

这是使用CellFormatting的{​​{1}}和CellParsing事件实现的。

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

您使用DataGridView事件,如下所示:

CellFormatting

使用这种方法,基础数据表与基础单元格值一样不受影响,因此格式化仍然可以像数字1和3那样工作。

然后,您需要在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"; } } } 事件中进行一些处理以将字符串转换回来。这又是因为您的基础表仍然有一个数字列。

如下所示,在解析的值未转换为int的情况下,仅使用单元格的实际值。但是,您可以在此处理程序中执行任何操作:

CellParsing