0

I have the following code who take all the rows from DataGridView and add it in a text box, multiline. i want to display text in textbox in 3 columns.

Current code looks like this:pic1

And i want something like this to be shown:pic2

string billInfo = string.Empty;
foreach (DataGridViewRow row in dataGridView2.Rows)
{
    billInfo = string.Format("{0}{1} {2} lei  Cod Produs:{3}{4}", billInfo, row.Cells["dataGridViewTextBoxColumn1"].Value, row.Cells["dataGridViewTextBoxColumn3"].Value, row.Cells["dataGridViewTextBoxColumn4"].Value, Environment.NewLine);
}
textBox1.Text = billInfo;
Nino
  • 6,931
  • 2
  • 27
  • 42
  • The textbox control isn't made to handle columns in this way. The only way you could do would be to count the number of characters in the first string: Telefon Apple ... Black for every line then get the longest and add 7 space and then add 7 space to the shorter one + empty space for every character the string has more. – Mederic May 18 '17 at 09:22
  • Or use a listbox. You would have to enable multi line in your text box anyway to show all the rows. – Wheels73 May 18 '17 at 09:24
  • there is any other way to do this? some code will be great if you can help – Sebastian George May 18 '17 at 09:25
  • i want to use the textbox bcs after i display the text i want to save it in a database. i dont know if i can take all the text from listbox and save it in a string. – Sebastian George May 18 '17 at 09:27
  • Here is a listbox example: https://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.multicolumn(v=vs.110).aspx and here is an example of formatting a string with identifical spacing. http://stackoverflow.com/questions/4784032/formatting-a-c-sharp-string-with-identical-spacing-in-between-values – jason.kaisersmith May 18 '17 at 09:32
  • the code you have provided works only if the first column have the same amount of characters – Sebastian George May 18 '17 at 09:36
  • If you want to save to a database just keep using the DataGridView as you can bind it to your database to directly updata and insert the data – Mederic May 18 '17 at 09:41
  • but i want to save it as a string. in only one field. i will try to use the advanced spacing that @jason.kaisersmith provided and i will come later with an update. – Sebastian George May 18 '17 at 09:53
  • it is very bad idea to store a table of data to database into one field. – Lei Yang May 18 '17 at 09:56
  • i know. is just for information. i cant make it work with advanced spacing. still i dont have any solution... – Sebastian George May 18 '17 at 10:03

2 Answers2

0

It would be better to use ListView. But, if you insist on TextBox, use fixed width font on your TextBox (font which have all letters with same width, such as Courier). Then, format your text with tabs (\t in string), like this:

billInfo = string.Format("{0}{1}\t\t{2}\t\tlei\t\tCod Produs:{3}{4}", 
    billInfo, 
    row.Cells["dataGridViewTextBoxColumn1"].Value, 
    row.Cells["dataGridViewTextBoxColumn3"].Value, 
    row.Cells["dataGridViewTextBoxColumn4"].Value, 
    Environment.NewLine);

experiment with number of tabs to achieve desired look.

Nino
  • 6,931
  • 2
  • 27
  • 42
0

If you really want to do this as a textbox, then it is probably best to create a new custom control based on textbox and use this to set the text as you wish. This is what I have done below. It needs refinement but will get you started.

public partial class ColumnTextBox : TextBox
{
    /// <summary>
    /// The string to use to separate the columns
    /// </summary>
    public string ColumnSeparator { get; set; }

    public ColumnTextBox()
    {
        InitializeComponent();
        this.Multiline = true;
        this.Font = new Font(FontFamily.GenericMonospace.Name, this.Font.Size);
        this.WordWrap = false;
        this.ScrollBars = ScrollBars.Both;
        this.ColumnSeparator = " ";
    }

    /// <summary>
    /// Set the Text data in folumn format
    /// </summary>
    /// <param name="rowData">the data to put into the text box</param>
    public void SetColumnText(List<List<string>> rowData)
    {
        //We manually set the font to ensure it is monospaced.  Without this, the method will not format the data in nice neat columns as we want
        this.Font = new Font(FontFamily.GenericMonospace.Name, this.Font.Size);
        if (rowData == null || rowData.Count == 0)
            throw new ArgumentException("Rowdata cannot be null or empty");

        if (rowData[0] == null || rowData[0].Count == 0)
            throw new ArgumentException("Rowdata must contain some column data");

        //the string format we will use
        string format = "{0,-?}";

        //determine the max size of every column, and store it
        int[] colMaxSizes = CalcMaxSizes(rowData);

        StringBuilder sb = new StringBuilder();

        //Loop through every row & column to build the string piece by piece
        foreach (List<string> row in rowData)
        {
            int col = 0;
            foreach (string data in row)
            {
                //append the data, using the format, padded to the max size.
                //Appened column separator to end
                sb.AppendFormat(format.Replace("?", colMaxSizes[col].ToString()), data).Append(ColumnSeparator);
                col++;
            }
            sb.Append(Environment.NewLine);
        }

        //Remove last newline
        string text = sb.ToString();
        this.Text = text.Substring(0, text.Length - 1);
    }

    /// <summary>
    /// Calculate the max size of every column
    /// </summary>
    /// <param name="rowData">The data to search through</param>
    /// <returns>An array contain the max size/lengt of the data in each column</returns>
    private int[] CalcMaxSizes(List<List<string>> rowData)
    {
        int[] maxSizes = new int[rowData[0].Count];
        foreach (List<string> row in rowData)
        {
            int col = 0;
            foreach (string data in row)
            {
                if (data.Length > maxSizes[col])
                    maxSizes[col] = data.Length;
                col++;
            }

        }

        return maxSizes;
    }
}

It is very important to make sure that you use a monospaced font, otherwise this will not work. This line ensures this;

this.Font = new Font(FontFamily.GenericMonospace.Name, this.Font.Size);

In this case yo build a list of lists of type string which represents your rows and columns and pass this to the method SetColumnText(). You might want to change this to use a collection or something else.

The method will then loop through the data and determine for each column what is the maximum width.
Next it will build the data and pad out each column to the maximum width of the data for that column.

It does this by using the String format "{0,-?}", where the ? is replaced by the maximum size for that column.

There is also a ColumnSeparator which allows you to define a different separator for the column, such as a tab.

You can use it like this;

List<List<string>> myData = new List<List<string>>();
//Build your data here
this.columnTextBox1.SetColumnText(myData);
jason.kaisersmith
  • 8,712
  • 3
  • 29
  • 51