如果数据集包含有一个列有时间戳或其他的二进制的价值,其相关的条件引发ArgumentException,当显示任何数据,列。是的,假定你有一些表包含二进制列如:

CREATE TABLE [dbo].[DataTest](
    [IdStuff] INT IDENTITY(1,1) NOT NULL,
    [ProblemColumn] TIMESTAMP NOT NULL )

在Visual Studio2008年,添加一个新的数据来源指向嫌疑人表。拖表的数据来源资源管理器上的视觉设计师的表面的一个新的WinForm自动创造条件下,BindingSource,等等。执行该应用程序和你会得到一个运行异常。听起来像一个缺陷,对吗?

如果你检查列收集的条件下,你会发现它规定所列类型DataGridViewImageColumn.为什么?因为,根据微软.净假定这二列的图像。事实上,Microsoft申明,这种行为是通过设计!看到这个缺陷的报告Microsoft Connect: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=93639

一种可以抑制该错误对话,通过处理DataError事件的条件,作为对话礼貌地表示,但这引出了一个问题。我想找到一种方法,以避免具有一个错误的状况在第一位。也就是说,我想要有一个DataGridViewTextColumn表示的文字表述的二进制数据,例如"0x1234a8e9433bb2".我在寻找一个通用的解决方案,自从我的实际代码没有使用特定表正如我在上面的例子。而我把一些任意的查询到一起到桥梁作用.消,然后调用

dataAdapter.Fill(dataTable)

自动生成数据表。由于它的条件,有的(恕我直言)错误,我认为我需要检查列表数据(即数据表。列[n]。数据类型。名称。等("字节[]")?),并将任何字节数,它们的文本形式手动之前,我连接的数据表要的条件与

bindingSource.DataSource = dataTable;

我的问题则:

是否有一个简单或更优雅的方式来显示的二列中的一个条件?

(注意这个问题的存在与这两个VS2005年和VS2008年.网2.0。净3.5.)

有帮助吗?

解决方案 2

的带动下由困惑的答案,再加上自发布我的问题有一个全新的视角:-)已经允许有足够的时间,我想出了下面的MorphBinaryColumns方法的幌子合理的清洁解决方案,嵌入在一个完整的样本测试程序(用于VS的设计者从含有单个的DataGridView我的WinForm生成的代码)。

MorphBinaryColumns检查列集合,并且对于每个这是一个二进制列, 生成与转换为十六进制字符串的值的新列,然后换出原始列用新的替换它,并保留原有的列的顺序。

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
  }

  private void Form1_Load(object sender, EventArgs e)
  {
    var sqlCnn = new SqlConnection("..."); // fill in your connection string
    string strsql = "select ... from ..."; // fill in your query

    var dataAdapter = new SqlDataAdapter();
    var dataTable = new DataTable();
    dataAdapter.SelectCommand = new SqlCommand(strsql, sqlCnn);
    dataAdapter.Fill(dataTable);
    MorphBinaryColumns(dataTable);
    dataGridView1.DataSource = dataTable;
  }

  private void MorphBinaryColumns(DataTable table)
  {
    var targetNames =  table.Columns.Cast<DataColumn>()
      .Where(col => col.DataType.Equals(typeof(byte[])))
      .Select(col => col.ColumnName).ToList();
    foreach (string colName in targetNames)
    {
      // add new column and put it where the old column was
      var tmpName = "new";
      table.Columns.Add(new DataColumn(tmpName, typeof (string)));
      table.Columns[tmpName].SetOrdinal(table.Columns[colName].Ordinal);

      // fill in values in new column for every row
      foreach (DataRow row in table.Rows)
      {
        row[tmpName] = "0x" + string.Join("",
          ((byte[]) row[colName]).Select(b => b.ToString("X2")).ToArray());
      }

      // cleanup
      table.Columns.Remove(colName);
      table.Columns[tmpName].ColumnName = colName;
    }
  }
}

其他提示

添加到上述方法的几个改进。 #1处理空二进制列,#2转换大量的列(并且使用相同的字符串生成器及以上),#8000 3最大显示长度,以避免转换真正大的二进制列的字符串的情况...#4创建临时柱改进的性能命名使用GUID以避免名称冲突的情况下,有一个名为“TEMP” ...

/// <summary>
/// Maximum length of binary data to display (display is truncated after this length)
/// </summary>
const int maxBinaryDisplayString = 8000;

/// <summary>
/// Accepts datatable and converts all binary columns into textual representation of a binary column
/// For use when display binary columns in a DataGridView
/// </summary>
/// <param name="t">Input data table</param>
/// <returns>Updated data table, with binary columns replaced</returns>
private DataTable FixBinaryColumnsForDisplay(DataTable t)
{
    List<string> binaryColumnNames = t.Columns.Cast<DataColumn>().Where(col => col.DataType.Equals(typeof(byte[]))).Select(col => col.ColumnName).ToList();
    foreach (string binaryColumnName in binaryColumnNames)
    {
        // Create temporary column to copy over data
        string tempColumnName = "C" + Guid.NewGuid().ToString();
        t.Columns.Add(new DataColumn(tempColumnName, typeof(string)));
        t.Columns[tempColumnName].SetOrdinal(t.Columns[binaryColumnName].Ordinal);

        // Replace values in every row
        StringBuilder hexBuilder = new StringBuilder(maxBinaryDisplayString * 2 + 2);
        foreach (DataRow r in t.Rows)
        {
            r[tempColumnName] = BinaryDataColumnToString(hexBuilder, r[binaryColumnName]);
        }

        t.Columns.Remove(binaryColumnName);
        t.Columns[tempColumnName].ColumnName = binaryColumnName;
    }
    return t;
}
/// <summary>
/// Converts binary data column to a string equivalent, including handling of null columns
/// </summary>
/// <param name="hexBuilder">String builder pre-allocated for maximum space needed</param>
/// <param name="columnValue">Column value, expected to be of type byte []</param>
/// <returns>String representation of column value</returns>
private string BinaryDataColumnToString(StringBuilder hexBuilder, object columnValue)
{
    const string hexChars = "0123456789ABCDEF";
    if (columnValue == DBNull.Value)
    {
        // Return special "(null)" value here for null column values
        return "(null)";
    }
    else
    {
        // Otherwise return hex representation
        byte[] byteArray = (byte[])columnValue;
        int displayLength = (byteArray.Length > maxBinaryDisplayString) ? maxBinaryDisplayString : byteArray.Length;
        hexBuilder.Length = 0;
        hexBuilder.Append("0x");
        for(int i = 0; i<displayLength; i++)
        {
            hexBuilder.Append(hexChars[(int)byteArray[i] >> 4]);
            hexBuilder.Append(hexChars[(int)byteArray[i] % 0x10]);
        }
        return hexBuilder.ToString();
    }
}

你可能会发现这很有用:http://social.msdn.microsoft.com/Forums/en/winformsdatacontrols/thread/593606df-0bcb-49e9-8e55-497024699743

基本上:

  • 获取数据,从数据库的数据表
  • 然后添加新的栏(类型(string))
  • 然后写的二进制的内容(使用 组以hex string)进入新栏

  • 然后据绑定.

这是简单的和令人讨厌的,但它有效地解决问题。

如何上,做了CAST该列视图立足查询?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top