Question Forms textbox multi line

gorf24

New member
Joined
Apr 24, 2022
Messages
2
Programming Experience
1-3
have a form with a textbox and set to multi lines i am sending the datetime and a line read from the serial port..
i have a new line sent also but the text in the textbox never seems to get the newline and scroll down, always over writes the line in the textbox.
any suggestions?

C#:
private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    in_data = "";
    in_data = ComPort.ReadLine();
    this.Invoke(new EventHandler(displaydata_event));
}

private void displaydata_event(object sender, EventArgs e)
{
    dateTime = DateTime.Now;
    string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
    data_in.Text = time + "\t\t\t" + in_data + "\n";
}

Thanks gary
 
Last edited by a moderator:
Of course it does. Think about what this line actually does:
C#:
data_in.Text = time + "\t\t\t" + in_data + "\n";
If you set the Text property to a value, why you expect the text displayed to be anything other than that value? If I set the name of my dog to "Rover" and then I set its name to "Spot", does that mean that it's now called "RoverSpot"? Of course not. The property value is the last value you assigned to it. That last value will replace anything that went before, not be combined with it. If you want a new value to be combined with the current value then that's for you to do:
C#:
data_in.Text = data_in.Text + time + "\t\t\t" + in_data + "\n";
or, more simply:
C#:
data_in.Text += time + "\t\t\t" + in_data + "\n";
That said, appending text in a TextBox is a common scenario, so it has been accounted for by the AppendText method:
C#:
data_in.AppendText(time + "\t\t\t" + in_data + "\n");
Not only will that append the text, it will place the caret at the end of the text, thus scrolling the control and displaying the new text. In contrast, setting the Text property will select all the text and scroll the control to the top, thus potentially hiding the new text.

This is an example of why you should ALWAYS read the documentation for new types and members. If you had read the documentation for the TextBox class then you would have seen the AppendText method. I soon lost count of the number of types and members that I saw when perusing documentation that came in useful later on. You won't always find what you need or understand what you find when you read documentation, but you'll get better at it the more you do it and it will be a substantial net gain.
 
A few other points about your post and your code. Firstly, I have formatted your code for easy reading. Please do so for us in future.

Secondly, what is the point of the first line here:
C#:
in_data = "";
in_data = ComPort.ReadLine();
Next, you should not be invoking an EventHandler. If there's no parameters and no return value then use a MethodInvoker, which provides the same additional performance as EventHandler. If there are parameters and/or a return value then use the appropriate generic Action or Func and take the insignificant performance hit. Your code would be better written like this:
C#:
private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    in_data = ComPort.ReadLine();
    this.Invoke(new MethodInvoker(DisplayData));
}

private void DisplayData()
{
    dateTime = DateTime.Now;
    string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
    data_in.Text = time + "\t\t\t" + in_data + "\n";
}
and better still like this:
C#:
private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    in_data = ComPort.ReadLine();
    this.Invoke(new Action<string>(DisplayData), in_data);
}

private void DisplayData(string in_data)
{
    dateTime = DateTime.Now;
    string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
    data_in.Text = time + "\t\t\t" + in_data + "\n";
}
That second option would mean getting rid of the field you're currently using to store the input.

Next, this is bad:
C#:
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
For one thing, it's bad because there will be no leading zeroes on single digit number, so one minute and one second past one o'clock would yield `"1:1:1"`, where it should be `"1:01:01"` or `"01:01:01"`. For another, formatting is built into the DateTime type. If you really wanted the format you already have then you'd use:
C#:
string time = dateTime.ToString("h:m:s");
but something like this would be better:
C#:
string time = dateTime.ToString("h:mm:ss");
Next, I would suggest that you use as few concatenation operators as possible. Personally, I pretty much never use two in the same line and sometimes not even that. You should prefer the String.Format method or, in newer versions of C#, string interpolation:
C#:
data_in.AppendText(String.Format("{0:h:mm:ss}\t\t\t{1}\n", DateTime.Now, in_data));
C#:
data_in.AppendText($"{DateTime.Now:h:mm:ss}\t\t\t{in_data}\n");
Finally, you should work on your naming. data_in for a TextBox and in_data for text to display in that TextBox? Not a good look.
 
A few other points about your post and your code. Firstly, I have formatted your code for easy reading. Please do so for us in future.

Secondly, what is the point of the first line here:
C#:
in_data = "";
in_data = ComPort.ReadLine();
Next, you should not be invoking an EventHandler. If there's no parameters and no return value then use a MethodInvoker, which provides the same additional performance as EventHandler. If there are parameters and/or a return value then use the appropriate generic Action or Func and take the insignificant performance hit. Your code would be better written like this:
C#:
private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    in_data = ComPort.ReadLine();
    this.Invoke(new MethodInvoker(DisplayData));
}

private void DisplayData()
{
    dateTime = DateTime.Now;
    string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
    data_in.Text = time + "\t\t\t" + in_data + "\n";
}
and better still like this:
C#:
private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    in_data = ComPort.ReadLine();
    this.Invoke(new Action<string>(DisplayData), in_data);
}

private void DisplayData(string in_data)
{
    dateTime = DateTime.Now;
    string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
    data_in.Text = time + "\t\t\t" + in_data + "\n";
}
That second option would mean getting rid of the field you're currently using to store the input.

Next, this is bad:
C#:
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
For one thing, it's bad because there will be no leading zeroes on single digit number, so one minute and one second past one o'clock would yield `"1:1:1"`, where it should be `"1:01:01"` or `"01:01:01"`. For another, formatting is built into the DateTime type. If you really wanted the format you already have then you'd use:
C#:
string time = dateTime.ToString("h:m:s");
but something like this would be better:
C#:
string time = dateTime.ToString("h:mm:ss");
Next, I would suggest that you use as few concatenation operators as possible. Personally, I pretty much never use two in the same line and sometimes not even that. You should prefer the String.Format method or, in newer versions of C#, string interpolation:
C#:
data_in.AppendText(String.Format("{0:h:mm:ss}\t\t\t{1}\n", DateTime.Now, in_data));
C#:
data_in.AppendText($"{DateTime.Now:h:mm:ss}\t\t\t{in_data}\n");
Finally, you should work on your naming. data_in for a TextBox and in_data for text to display in that TextBox? Not a good look.
Thanks i'm new at this, and just trying to get things to work don't expect it to look good or be great code for now.
i did figure it out at least got it to work with data_in.AppendText(time + "\t\t\t" + in_data + "\n");
it sends it to the textbox and now the \n works correct scrolls down
I also changed in the properties, Accepts Return to false was set true, not sure if that mattered did them both at the same time.

Thanks for your help
gary

And i do have an event handler thought i included it in the code that i attached
 
I also changed in the properties, Accepts Return to false was set true, not sure if that mattered did them both at the same time.
That has no impact. That is used to determine what happens if the user pressed the Return key while in the multiline text box. If set true, a new line and line feed is inserted into the textbox. If false, the default button of the window that contains the textbox is pressed.

As an aside, in WinForms, since you are on Windows, text should have "\r\n" to denote an end of line. This is different from Linux which only uses "\n", or older Macs which used only "\r". Use Environment.NewLine if you want the system to determine the correct one for you.
 
Back
Top Bottom