4

I have a Domain Class User with the Following properties (Fields):

UserId (int)
UserName (nvarchar(25))
SecurePassword (varbinary(32))
Salt (varbinary(32))

SecurePassword and Salt store a byte array with a length of 32 as you may have guessed. If I set my

BindingSource.DataSource = context.Users.Local.ToBindingList();

And then my

DataGridView.DataSource = BindingSource;

I’ll get an Error telling me to Handle the DataError Event for the GridView. Once I do that with an empty method the SecurePassword and Salt Columns show [X] for every row.

Now, I could use linq to render that in an anonymous type as:

 var data = from u in context.Users
            select new
            {
                u.UserId,
                u.UserName,
                SecurePassword = BitConverter.ToString(u.SecurePassword),
                Salt = BitConverter.ToString(u.Salt)
            };

But I really don’t want an anonymous type. In WPF I could have written a Converter that inherits from IValueConverter, but that doesn’t seem to be available in WinForms. Any help would be greatly appreciated and welcomed.

3 Answers 3

3

Use CellFormatting event. Something like:

void dataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    // 2 - Salt, 3 - SecurePassword
    if (e.ColumnIndex == 2 || e.ColumnIndex == 3)
    {
        if (e.Value != null)
        {
            byte[] array = (byte[])e.Value;
            e.Value = BitConverter.ToString(array);
            e.FormattingApplied = true;
        }
        else
            e.FormattingApplied = false;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for a prompt answer that work very well. I did need to set AutoGenerateColumns to false and add Columns manually. Still, it worked great.
1

To build upon the other answer, the simplest way I achieved this was:

  1. Go into Properties of your DataGridView, find the Columns property, edit it, and change the ColumnType of your binary columns to DataGridViewTextBoxColumn.
  2. Go into the Events pane and generate a method on the CellFormatting event.
  3. Set the code of the method to be something like:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.ColumnIndex == 1 || e.ColumnIndex == 2)
    {
        if (e.Value != null)
        {
            e.Value = Encoding.UTF8.GetString((byte[]) e.Value);
            e.FormattingApplied = true;
        }
        else
            e.FormattingApplied = false;
    }
}

Comments

1

I had a similar issue when binding to a table with byte data in it so I wrote the following method that creates a new text column, adds it to the table, copies over the data from the byte column while converting it to a string, moves the new column to the position of the old column, and deletes the old column

Here is the code in vb

Private Sub ReplaceByteColumns(table As DataTable)
    Dim byteColumns As New Dictionary(Of DataColumn, DataColumn)
    For Each column As DataColumn In table.Columns
        If column.DataType = GetType(Byte()) Then
            Dim byteColumn As New DataColumn
            byteColumn.DataType = GetType(String)
            byteColumns.Add(column, byteColumn)
        End If
    Next

    For Each column As DataColumn In byteColumns.Keys
        Dim byteColumn As DataColumn = byteColumns(column)
        table.Columns.Add(byteColumn)
        For Each row As DataRow In table.Rows
            row.Item(byteColumn) = BitConverter.ToString(CType(row.Item(column), Byte()))
        Next
        byteColumn.SetOrdinal(column.Ordinal)
        byteColumn.ReadOnly = True
        table.Columns.Remove(column)
        byteColumn.ColumnName = column.ColumnName
    Next
End Sub

Here is the code auto converted to C# using https://www.carlosag.net/tools/codetranslator/

private void ReplaceByteColumns(DataTable table) {
    Dictionary<DataColumn, DataColumn> byteColumns = new Dictionary<DataColumn, DataColumn>();
    foreach (DataColumn column in table.Columns) {
        if ((column.DataType == typeof(byte[]))) {
            DataColumn byteColumn = new DataColumn();
            byteColumn.DataType = typeof(string);
            byteColumns.Add(column, byteColumn);
        }

    }

    foreach (DataColumn column in byteColumns.Keys) {
        DataColumn byteColumn = byteColumns[column];
        table.Columns.Add(byteColumn);
        foreach (DataRow row in table.Rows) {
            row.Item[byteColumn] = BitConverter.ToString(((byte[])(row.Item[column])));
        }

        byteColumn.SetOrdinal(column.Ordinal);
        byteColumn.ReadOnly = true;
        table.Columns.Remove(column);
        byteColumn.ColumnName = column.ColumnName;
    }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.