How to check selected text in multi line text Box in C#? - c#

I have two Multi-Line Text Boxes and one arrow button in my application and what I want is that when a user selects any one or many lines from Multi-Line textbox 1 ,it should update the status of that line from 0 to 1 and then I want to load the rows whose status is 1 into Multi-Line textbox 2.I have tried but didn't know what should I do next?
Code:
for (int i = 0; i < txtNewURLs.Lines.Length; i++)
{
if (txtNewURLs.Lines[i].Select)
{
}
}
Can any body please help me or give some suggession to do this task?

Assuming you are using a Multiline TextBox similar to MSDNS's How to: Create a Multiline TextBox Control, you can utilize the SelectedText property to retrieve the text that the user has selected. The lines will be separated by \r\n
i.e.
If I have the below (inbetween the page lines):
test0
test1
And I selected lines test0 and test1, then SelectedText would be test0\r\ntest1.
You could then split on the \r\n and retrieve each selected line.
// Retrieve selected lines
List<string> SelectedLines = Regex.Split(txtNewURLs.SelectedText, #"\r\n").ToList();
// Check for nothing, Regex.Split returns empty string when no text is inputted
if(SelectedLines.Count == 1) {
if(String.IsNullOrWhiteSpace(SelectedLines[0])) {
SelectedLines.Remove("");
}
}
// Retrieve all lines from textbox
List<string> AllLines = Regex.Split(txtNewURLs.Text, #"\r\n").ToList();
// Check for nothing, Regex.Split returns empty string when no text is inputted
if(AllLines.Count == 1) {
if(String.IsNullOrWhiteSpace(AllLines[0])) {
AllLines.Remove("");
}
}
string SelectedMessage = "The following lines have been selected";
int numSelected = 0;
// Find all selected lines
foreach(string IndividualLine in AllLines) {
if(SelectedLines.Any(a=>a.Equals(IndividualLine))) {
SelectedMessage += "\nLine #" + AllLines.FindIndex(a => a.Equals(IndividualLine));
// Assuming you store each line status in an List, change status to 1
LineStatus[AllLines.FindIndex(a => a.Equals(IndividualLine));] = 1;
numSelected++;
}
}
MessageBox.Show((numSelected > 0) ? SelectedMessage : "No lines selected.");

Related

Format DataGridView TextBox Column Containing Numeric Values

I have a DataGridView with TextBox colums. One of the columns display record counts which are formatted as ###,###,000. The column itself isn't set to format the text, but the data is formatted when the data source is populated. The data source is a List by the way. The DataGridView merely displays everything as it gets it.
Now, I need to parse the numeric text value into a variable, which is fine by doing
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString())
but, if I have numbers reaching thousands, it displays as 1 000, because of the formatting. The formatting generates a space rather than a comma as this is how the environment has been configured. When I try to parse that value, I get an exception because of the space in the numeric value.
I have tried formatting the string value
int.Parse(String.Format("{0:000000000}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
and
int.Parse(String.Format("{0:########0}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
and all sorts of variants, but it keeps returning the space in the value, which then won't parse. I have tried replacing the space, but it is persistent. Also, the space shows ASCII keycode 63 which is supposed to be a question mark, not so? Even when I try to replace using the keycode... nothing!
Any ideas as to why this is happening and how to fix it?
The complete code block I have is
foreach (DataGridViewRow data_grid_view_row in dgv_Migration_Files.Rows)
{
if ((bool)data_grid_view_row.Cells["col_Select"].Value == true)
{
//-------------------------------------------------------------------------
// this is only to test and see what value I get for the space character, will be removed later
string test_str = data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(" ", string.Empty);
test_str = test_str.Replace(" ", "");
for (int k = 0; k < test_str.Length; k++)
{
string newstr = test_str.Substring(k, 1);
var kycode = ASCIIEncoding.ASCII.GetBytes(newstr);
}
//-------------------------------------------------------------------------
migrate.Add(new Migrate()
{
File_Folder = data_grid_view_row.Cells["col_File_Folder"].Value.ToString()
,
File_Name = data_grid_view_row.Cells["col_File_Name"].Value.ToString()
,
Record_Count = int.Parse(String.Format("{0:000000000}", data_grid_view_row.Cells["col_Record_Count"].Value.ToString()))
});
}
}
Use simple Solution:-
If space is available Remove it and then simply Parse into INT.
str.Replace(" ", String.Empty)
string data = data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(" ", String.Empty);
int.Parse(data);
Make it easier:-
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().replace(" ", String.Empty));
And if you want to remove space and comma both while parsing using this Regular Expression
int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().replace(/[, ]+/g, " ").trim());
Check This Small Example First you will get Clear Idea:-
string data = "1 0000";
string result = data.Replace(" ", string.Empty);
Since the replace method didn't remove spaces as I expected to, I resorted to the below solution. This will also remove any other numeric separators irrespective of what the numeric separator has been set up as in the OS.
//get the numeric decimal seperator key code
string dummy_numeric = (1000).ToString(Helper.application_number_display_format);
char replace_char = (char)0;
foreach (char current_char in dummy_numeric)
{
if (!System.Char.IsDigit(current_char))
{
replace_char = current_char;
break;
}
}
//get all the files that are selected for migration
List<Migrate> migrate = new List<Migrate>();
foreach (DataGridViewRow data_grid_view_row in dgv_Migration_Files.Rows)
{
if ((bool)data_grid_view_row.Cells["col_Select"].Value == true)
{
migrate.Add(new Migrate()
{
File_Folder = data_grid_view_row.Cells["col_File_Folder"].Value.ToString()
,
File_Name = data_grid_view_row.Cells["col_File_Name"].Value.ToString()
,
Record_Count = int.Parse(data_grid_view_row.Cells["col_Record_Count"].Value.ToString().Replace(replace_char.ToString(), ""))
});
}
}

Print Multiple Columns of Data to Label c#

I am creating a GUI that outputs raw serial data onto a textbox, and I want the user to be able to choose certain columns from that data to print onto a label next to the text box every time the data updates. I can do this when there is only one column chosen, however, when I try to add multiple columns, I get the error "Cannot Explicitly Convert string[] to string". How can I take multiple columns of data, put them into one string, then print the string to the label?
Here is what I have done so far:
string[] data_disp = new string[10];
string[] blahArray = line.Split(new char[] { ',' });
int count1 = txt_PRINT_COLUMN_2.Text.Split(',').Length - 1;
string[] countarr = txt_PRINT_COLUMN_2.Text.Split(new char[] { ',' });
for (int i = 0; i <= count1;)
{
int column_data = Convert.ToInt32(countarr[i]);
double inst2 = Convert.ToDouble(blahArray[column_data]);
data_disp[i] = Convert.ToString(inst2);
i++;
}
lbl_SHOW_COLUMN_2.Text = String.Join(",",data_disp);
"line" is the incoming data, txt_PRINT_COLUMN_2 is the textbox where the user enters the desired columns, and lbl_SHOW_COLUMN_2 is the label where the data should print.
EDIT: I used string.join which takes care of the string error, however, the string data_disp is still null. How do I fill it in with the values?
EDIT2: I added i++ to the for loop and made the condition for i <= count1. This worked for the first iteration, however, when the data updated, I got the error: "Input string was not in the correct format" on the line inst2. How do I fix this?

C# string problems

I have a multiline text box called txtOutput that receives messages from the serial port. Each new message is a new line and represents a number from 1 to a maximum of 4 digits.
The method used to add the data in the multiline textbox is an append.
I have no problems with the above feature, it is working fine.
I would like to take the last message from the txtOutput and show it in textBox2 if the number is less than 1000, and in textbox3 if it is not. Then both text boxes would be updated.
I would appreciate if someone can give in an example especially in how to get the last message from the multiline textbox to a variable and how to update the textboxes if there is a new value.
You should save the last message (from the serial port) in a variable such as lastSerialMesssage. You can then convert this value to an integer and use a conditional statement to check if the value is smaller than 1000, if it is, set TextBox3 to the last serial message value, else set the value to TextBox2.
string lastSerialMessage = SerialPortMessage;
int lastMessageValue;
Int32.TryParse(lastSerialMessage, out lastMessageValue);
if (lastMessageValue < 1000)
{
TextBox3.Text = lastSerialMessage;
} else {
TextBox2.Text = lastSerialmessage;
}
http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Thanks to all for the suggestions but as I mentioned in my comments, the suggested methods did not work because the content of the string was not accurate and I ended up receiving in the textBox 2 and 3 only part of the data and not always. I have solved the problem (thanks to other advices) using RegEx in this way:
if (txtOutput.Text.Length > 0)
{
MatchCollection mc = Regex.Matches(txtOutput.Text, #"(\+|-)?\d+");
if (mc.Count > 0)
{
long value = long.Parse(mc[mc.Count - 1].Value);
if (value < 1000)
{
textBox2.Text = value.ToString();
}
else
{
value = value - 1000;
textBox3.Text = value.ToString();
}
}
}
this is working fine and no piece of information are lost.Thanks again for your advices.

How do you create a WYSIWYG TextBox control editor for vertically centered messages sent to a mobile device?

I have a WPF TextBox that holds seven lines of text and has word wrapping enbabled.
<TextBox TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" MaxLines="7"/>
As you can see in the XAML above the text is centered vertically and horizontally. When I type a short phrase that fits on a single line, the text appears on the 4th line of the control as expected since the VerticalContentAlignment is "Center".
The text that is entered by the user is meant to be sent to a mobile device that has a display that holds seven lines of text and uses the "\n" to wrap to the next line. The intent is that the display of text on the mobile device looks the same as what is entered into the TextBox control. At least as far as number of lines of text, centering, and where line breaks occur.
So when the the user finishes entering the text into the TextBox control and clicks the "Send Message" button, some post-processing must be done on the entered text before sending it to the mobile device.
The text entered into TextBox control needs to have newline (\n) characters added wherever the text wraps to a new line in the TextBox control. For example, in cases where the control is showing multiple lines of text, I copy the TextBox's text and add a newline between the lines wehre the TextBox control wrapped the lines of text that were entered by the user.
So when the user clicks a "Send Message" button this is the code that does the post processing:
public static String AddNewLineCharsToMessage(TextBox textBox)
{
String message = String.Empty;
if (textBox == null) return message;
// First strip all the carriage returns and newline characters
// so we don't have duplicate newline characters in the message.
// Then add back in just the newline characters which is what the
// mobile device uses to wrap lines.
// Just assign the text if we have a single line message
if (textBox.LineCount < 2)
return textBox.Text;
var textLines = new List<string>(5);
int lineCount = Math.Min(textBox.LineCount, textBox.MaxLines);
for (Int32 index = 0; index < lineCount; index++)
{
if (textBox.GetLineText(index).Length > 0)
{
textLines.Add(textBox.GetLineText(index));
textLines[index] = textLines[index].Replace("\r", "");
textLines[index] = textLines[index].Replace("\n", "");
}
else
textLines.Add("\n");
}
message = String.Empty;
for (Int32 index = 0; index < lineCount; index++)
message += textLines[index] + (index < lineCount - 1 ? "\n" : "");
return message;
}
Given the code above, I would expect the output for a single line of text to look something like: "\n\n\n\nFoo". However, the output is "\nFoo\nFoo\nFoo\nFoo". Setting a break point in the code I see that textBox.GetLineText(index) for indices 0 through 3 returns "Foo" for each index even though "Foo" is only shown once in the TextBox control.
So I guess I really have two questions:
1) Why does GetLineText return a LineCount of 4 with every line having the same text, when only a single line of text (that fits on one line in the TextBox control) was entered by the user?
2) What is an easy way to work around this, keep the entered text centered in the TextBox control, and send the remote device the text message that will be displayed as seen by the user on the TextBox control?
Notes:
I cannot simply remove duplicate lines of text and replace them with "\n" as the user may have typed in the same text on multiple lines. Also, I could simply align the entered text to the vertical top instead of the vertical center. I have verified this works, but does not give a true WYSIWIG experience.
Looks like a bug in the method. You could work around this by either wrapping the textbox with another control that does the vertical centering or by extracting the lines via the text property.
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<TextBox AcceptsReturn="True" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" BorderThickness="0"> </TextBox>
</StackPanel>
The following modified code from the method shown above solves the problem. I am still curious however if Microsoft has a bug with the textBox.GetLineText method.
public static String AddNewLineCharsToMessage(TextBox textBox)
{
String message = String.Empty;
if (textBox == null) return message;
// Just assign the text if we have a single line message
if (textBox.LineCount < 2)
return textBox.Text;
// Find the index for the first line that contains text displayed in the TextBox.
// GetLineText(index) will return the text displayed/entered by the user for indices less
// than the index of the line that the text is actually displayed on. This seems to be
// a bug to me, but I will workaround this Microsoft weirdness.
// Find the index of first line that actually displays text by using the length of TextBox.Text
Int32 firstTextLineIndex = 0;
Int32 textLen = textBox.Text.Length;
Int32 textLinesLen = 0;
for (Int32 firstTextLine = textBox.LineCount - 1; firstTextLine >= 0; firstTextLine--)
{
textLinesLen += textBox.GetLineText(firstTextLine).Length;
if (textLinesLen >= textLen)
{
firstTextLineIndex = firstTextLine;
break;
}
}
// First strip all the carriage returns and newline characters
// so we don't have duplicate newline characters in the message.
// Then add back in just the newline characters which is what the car
// code uses to parse out the message to be displayed on each line.
var textLines = new List<string>(5);
int lineCount = Math.Min(textBox.LineCount, textBox.MaxLines);
for (Int32 index = 0; index < lineCount; index++)
{
if (index < firstTextLineIndex)
textLines.Add("");
else // if (textBox.GetLineText(index).Length > 0)
{
textLines.Add(textBox.GetLineText(index));
textLines[index] = textLines[index].Replace("\r", "");
textLines[index] = textLines[index].Replace("\n", "");
}
}
message = String.Empty;
for (Int32 index = 0; index < lineCount; index++)
message += textLines[index] + (index < lineCount - 1 ? "\n" : "");
return message;
}

txt file read/overwrite/append. Is this feasible? (Visual C#)

I'm writing a program for some data entry I have to periodically do. I have begun testing a few things that the program will have to do but i'm not sure about this part.
What i need this part to do is:
read a .txt file of data
take the first 12 characters from each line
take the first 12 characters from each line of the data that has been entered in a multi-line text box
compare the two lists line by line
if one of the 12 character blocks from the multi-line text box match one of the blocks in the .txt file then overwrite that entire line (only 17 characters in total)
if one of the 12 character blocks from the multi-line text box DO NOT match any of the blocks in the.txt file then append that entire line to the file
thats all it has to do.
i'll do an example:
TXT FILE:
G01:78:08:32 JG05
G08:80:93:10 JG02
G28:58:29:28 JG04
MULTI-LINE TEXT BOX:
G01:78:08:32 JG06
G28:58:29:28 JG03
G32:10:18:14 JG01
G32:18:50:78 JG07
RESULTING TXT FILE:
G01:78:08:32 JG06
G08:80:93:10 JG02
G28:58:29:28 JG03
G32:10:18:14 JG01
G32:18:50:78 JG07
as you can see lines 1 and 3 were overwriten, line 2 was left alone as it did not match any blocks in the text box, lines 4 and 5 were appended to the file.
thats all i want it to do.
How do i go about this?
Thanks in advance
Edit
The code i'm using is this:
private void WriteToFile()
{
// Read all lines from file into memory
System.IO.StreamReader objReader = new System.IO.StreamReader("Jumpgate List.JG");
List<String> fileTextList = new List<String>();
do
{
fileTextList.Add(objReader.ReadLine());
}
while (objReader.Peek() != -1);
objReader.Close();
// Read all lines from the Input textbox into memory
System.IO.StringReader objReaderi = new System.IO.StringReader(txtInput.Text);
List<String> inputTextList = new List<String>();
do
{
inputTextList.Add(objReaderi.ReadLine());
}
while (objReaderi.Peek() != -1);
objReaderi.Close();
for(int i=0;i<fileTextList.Count;i++)
{
for(int j=0;j<inputTextList.Count;j++)
//compare the first 12 characters of each string
if (String.Compare(fileTextList[i], 0, inputTextList[j], 0, 12) == 0) // strings are equal
{
//replace the fileTextList string with the inputTextList string
fileTextList[i] = inputTextList[j];
// now that you have matched you inputTextList line you remember not to append it at the end
inputTextList[j] = String.Empty; // or nothing
}
}
for(int i=0;i<inputTextList.Count;i++)
{
if (!string.IsNullOrEmpty(inputTextList[i])) fileTextList.Add(inputTextList[i]);
}
System.IO.StreamWriter objWriter = new System.IO.StreamWriter("Jumpgate List.JG");
// Overwrite the Jumpgate List.JG file using the updated fileTextList
objWriter.Write(fileTextList);
objWriter.Close();
}
However, when i open the txt file all i get is: System.Collections.Generic.List`1[System.String]
I'm not going to write the whole code for doing this but it would be something like this:
Disclaimer: I have not used a code editor to try the code, just wrote it here, hopefully you'll get the idea and fill in the missing pieces :)
1) get all the lines in the file in a list. Something like this
StreamReader rd = new StreamReader("sadasd");
List<String> llist = new List<String>();
do
{
llist.Add(rd.ReadLine());
} while (rd.Peek() != -1);
2) get all the lines in your multiline text box (the procedure should be similar to the one above): multiTextList
3) now that you can compare the content of the 2 lists iterating through them
for(int i=0;i<fileTextList.Count;i++)
{
for(int j=0;j<multiTextList.Count;j++)
//compare the first 12 characters of each string
if String.Compare(fileTextList[i], 0, multiTextList[j], 0, 12) == 0 // strings are equal
{
//replace the initial line with whatever you want
fileTextList[i] = //whatever
// now that you have matched you multiTextList line you remember not to append it at the end
multiTextList[j] = String.empty // or nothing
}
}
4) at the end you will have in fileTextList the initial rows, modified where necessary
In multiTextList you will have only the lines that were not matched so we add them to the initial file rows
for(int i=0;i<multiTextList.Count;i++)
{
if !string.isnullorempty(multitextlist[i]) fileTextList.add(multitextlist[i])
}
5) now in fileTextList you have all the rows you require so you can print them one by one in a file and you have your result
StringBuilder lSb = new StringBuilder();
for (int i = 0; i < fileTextList.Count; i++)
{
lSb.AppendLine(fileTextList[i]);
}
File.WriteAllText(#"C:/test2.txt",lSb.ToString());
In C:/test2.txt you should have the results.
Hope this helps!
// this variable maps the timestamps to complete lines
var dict = new Dictionary<string, string>();
// create the map of stamp => line for the original text file
string fileLine = file.ReadLine();
string fileStamp = fileLine.Substring(0, 12);
dict[fileStamp] = fileLine;
// now update the map with results from the text input. This will overwrite text
// strings that already exist in the file
foreach (string inputLine in textInputString.Split('\n'))
{
string inputStamp = inputLine.Substring(0, 12);
dict[inputStamp] = inputLine;
}
// write out the new file with the updated lines
foreach (string line in dict.Values)
{
outputFile.WriteLine(line);
}
if the file is large, loading the entire file into a dictionary to update a handful of lines from a textfield is probably excessive.
In pseudocode I would probably:
Create a list of booleans or other structure to track if a line was matched.
open the file in read/write mode.
For each line in file
{
for each unmatched line in text field
{
If stamps match
Update file
record that it was matched
}
}
for each unmatched line in text field
{
append to file
}
If the lines are fixed width, you can probably optimize by only reading the stamp rather than the whole line. If they match your file pointer is in the right spot to start writing, if not you move to the next line.

Categories