How can i use a numericUpDown to move to specific location text in richTextBox? - c#

In the listView selected index i select item and display the file content in richTextBox:
void lvnf_SelectedIndexChanged(object sender, EventArgs e)
{
if (ListViewCostumControl.lvnf.SelectedItems.Count > 0)
{
richTextBox1.Text = File.ReadAllText(ListViewCostumControl.lvnf.Items[ListViewCostumControl.lvnf.SelectedIndices[0]].Text);
int resultsnumber = 0;
int start = richTextBox1.SelectionStart;
int startIndex = 0;
int index = 0;
string word = textBox1.Text;
Color selectionColor = richTextBox1.SelectionColor;
word = textBox1.Text.Replace("\r\n", "\n");
while ((index = richTextBox1.Text.IndexOf(word, startIndex)) != -1)
{
richTextBox1.Select(index, word.Length);
richTextBox1.SelectionColor = Color.Yellow;
startIndex = index + word.Length;
resultsnumber ++;
}
richTextBox1.SelectionStart = start;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = selectionColor;
label16.Text = resultsnumber.ToString();
label16.Visible = true;
numericUpDown1.Maximum = resultsnumber;
numericUpDown1.Enabled = true;
}
}
And i have the numericUpDown changedvalue event
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
}
for example if i have in the numericUpDown the maximum value of 4 that's 4 results in the richTextBox text.
Each result is in another place in the text.
What i want to do is when i move up down with the numericUpDown it will jump in the richTextBox to the result location in the text.
I think it should be that if the first result started in index 0 and ended in index 20 then jump to this result show this result.
If the third result is started in index 76 and ended in index 83 so if i selected in the numericUpDown the value 3 jump to this result location.
Ok this is what i did now it was quite easy but i have a problem reseting the variable:
It was easy to do it but i have a problem reseting the variables when selecting another item each time in the listView. I want to reset the List and also to set the numericUpDown1 to value 0 when selecting other item. But then it's going to the numericUpDown1_ValueChanged item before it's adding items to the List and throw exception since the List Count and the numericUpDown1 value are 0.
In top of form1 created a new List
private List<int> results = new List<int>();
In the listView selectedindex event:
void lvnf_SelectedIndexChanged(object sender, EventArgs e)
{
if (ListViewCostumControl.lvnf.SelectedItems.Count > 0)
{
richTextBox1.Text = File.ReadAllText(ListViewCostumControl.lvnf.Items[ListViewCostumControl.lvnf.SelectedIndices[0]].Text);
results = new List<int>();
numericUpDown1.Value = 0;
int resultsnumber = 0;
int start = richTextBox1.SelectionStart;
int startIndex = 0;
int index = 0;
string word = textBox1.Text;
Color selectionColor = richTextBox1.SelectionColor;
word = textBox1.Text.Replace("\r\n", "\n");
while ((index = richTextBox1.Text.IndexOf(word, startIndex)) != -1)
{
richTextBox1.Select(index, word.Length);
richTextBox1.SelectionColor = Color.Yellow;
startIndex = index + word.Length;
resultsnumber ++;
results.Add(startIndex);
}
richTextBox1.SelectionStart = start;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = selectionColor;
label16.Text = resultsnumber.ToString();
label16.Visible = true;
numericUpDown1.Maximum = results.Count -1;
numericUpDown1.Enabled = true;
richTextBox1.SelectionStart = results[(int)numericUpDown1.Value];
richTextBox1.ScrollToCaret();
}
}
In the numericupdown1 valuechanged event
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if (results.Count == 0)
{
MessageBox.Show("Results Count Value is 0 Check It !!!!!");
}
else
{
richTextBox1.SelectionStart = results[(int)numericUpDown1.Value];
richTextBox1.ScrollToCaret();
}
}
When selecting first item in the listView it's fine.
But then when selecting any other item i want that the results List and the numericUpDown will be reset to empty and 0.
The problem is when i set the numericUpDown1 Value to 0 it's jumping to the valuechanged event before it's adding the results to the List so it's giving the exception.

Related

The number of times a word is repeated in the text box

How can I make the program count how often a Pre-selected word is repeated and put it in a new text box called result and this code to colors the chosen word. What should i do now?.
int index = 0;
string temp = richTextBox1.Text;
richTextBox1.Text = "";
richTextBox1.Text = temp;
while (index < richTextBox1.Text.LastIndexOf(word.Text))
{
richTextBox1.Find(word.Text, index, richTextBox1.TextLength, RichTextBoxFinds.None);
richTextBox1.SelectionBackColor = Color.Blue;
index = richTextBox1.Text.IndexOf(word.Text, index) + 1;
result.Text = //???
This might help you to set the BackColor of the words and also output the count.
int i = richTextBox1.Text.IndexOf(word.Text);
int count = 1;
while (i > -1)
{
richTextBox1.Select(i, word.Text.Length);
richTextBox1.SelectionBackColor = Color.Blue;
i = richTextBox1.Text.IndexOf(word.Text, i + 1);
result.Text = count++.ToString();
}

Limit line length in multiline textbox

I need to limit the number of characters on a single line that a user can enter into a multiline textbox. I have a function that can do that for data typed in, but not for data cut and pasted in.
I've tried reading the textbox into an array, using substring, and copying back to the text string, but this code (posted) throws an exception.
private void LongLine_TextChanged(object sender, TextChangedEventArgs e)
{
int lineCount =
((System.Windows.Controls.TextBox)sender).LineCount;
//string newText = "";
for (int i = 0; i < lineCount; i++)
{
if
(((System.Windows.Controls.TextBox)sender).GetLineLength(i) > 20)
{
string textString = ((System.Windows.Controls.TextBox)sender).Text;
string[] textArray = Regex.Split(textString, "\r\n");
textString = "";
for (int k =0; k < textArray.Length; k++)
{
String textSubstring = textArray[k].Substring(0, 20);
textString += textSubstring;
}
((System.Windows.Controls.TextBox)sender).Text = textString;
}
}
e.Handled = true;
}
This does what you seem to be asking for:
It truncates the end of any line that is longer than 20 as you type and when you paste or otherwise change the text.
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
const int MAX_LINE_LENGTH = 20;
var textbox = sender as TextBox;
var exceedsLength = false;
// First test if we need to modify the text
for (int i = 0; i < textbox.LineCount; i++)
{
if (textbox.GetLineLength(i) > MAX_LINE_LENGTH)
{
exceedsLength = true;
break;
}
}
if (exceedsLength)
{
// Split the text into lines
string[] oldTextArray = textbox.Text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var newTextLines = new List<string>(textbox.LineCount);
for (int k = 0; k < oldTextArray.Length; k++)
{
// truncate each line
newTextLines.Add(string.Concat(oldTextArray[k].Take(MAX_LINE_LENGTH)));
}
// Save the cursor position
var cursorPos = textbox.SelectionStart;
// To avoid the text change calling back into this event, detach the event while setting the Text property
textbox.TextChanged -= TextBox_TextChanged;
// Set the new text
textbox.Text = string.Join(Environment.NewLine, newTextLines);
textbox.TextChanged += TextBox_TextChanged;
// Restore the cursor position
textbox.SelectionStart = cursorPos;
// if at the end of the line, the position will advance automatically to the next line, supress that
if (textbox.SelectionStart != cursorPos)
{
textbox.SelectionStart = cursorPos - 1;
}
}
e.Handled = true;
}

How to sum datagridview selected cell CORRECTLY

it's working but not correctly
... if selecting from up to down it's sum correct somewhere, but Down to up select doesnt summing
private void SalesGridView_SelectionChanged(object sender, EventArgs e)
{
float sumNumbers = 0;
for (int i = 0; i < SalesGridView.SelectedCells.Count; i++)
{
if (!SalesGridView.SelectedCells.Contains(SalesGridView.Rows[i].Cells["TotalBillColumn"]))
{
float nextNumber = 0;
if (float.TryParse(SalesGridView.SelectedCells[i].FormattedValue.ToString(), out nextNumber))
sumNumbers += nextNumber;
label1.Text = "selected value " + sumNumbers;
label2.Text = "nr selected cells " + SalesGridView.SelectedCells.Count.ToString();
}
else
{
}
}
}
Try the following code:
private void SalesGridView_SelectionChanged(object sender, EventArgs e)
{
float sumNumbers = 0;
for (int i = 0; i < SalesGridView.SelectedCells.Count; i++)
{
var selectedCell = SalesGridView.SelectedCells[i];
if (selectedCell.ColumnIndex == SalesGridView.Columns["TotalBillColumn"].Index)
{
float nextNumber = 0;
if (float.TryParse(selectedCell.FormattedValue.ToString(), out nextNumber))
sumNumbers += nextNumber;
}
}
label1.Text = "selected value " + sumNumbers;
label2.Text = "nr selected cells " + SalesGridView.SelectedCells.Count.ToString();
}
Sorry, for the late explanation, when I wrote that answer didn't have time to elaborate what your actual problem is and only gave you a solution that should work.
Your problem can be located at that line:
if (!SalesGridView.SelectedCells.Contains(SalesGridView.Rows[i].Cells["TotalBillColumn"]))
To be precise the following statment will give you wrong results:
SalesGridView.Rows[i]
You will receive unwanted results, because i doesn't fit your requirement of an index of your Rows, so lets look at what you wrote in your for loop.
for (int i = 0; i < SalesGridView.SelectedCells.Count; i++)
Your for loop tries to enumerate the SelectedCells of your SalesGridView.
So lets assume you select 5 cells, than your for loop with enumerate from 0 to exclusive 5, so i will be 0, 1, 2, 3 or 4.
Now lets check again with the problematic statement I mentioned earlier:
SalesGridView.Rows[i]
Does the SelectedCell with for example i = 0 correspone with Rows[0] no it doesn't have to.
Your SelectedCells could be of any row and your for loop will always enumerate from 0 to SelectedCells.Count but your statementment of SalesGridView.Rows[i] will always try to get the Row with the given index of i.
So, for example:
You select 2 cells in row 6 and 7.
SelectedCells.Count will have 2
You enumerate SelectedCells beginning from 0 to exclusive 2, so i will be 0 or 1
Inside your loop you try to access the row with i, by calling SalesGridView.Rows[i]
as mentioned in point 3. i will only be 0 or 1, but I selected 2 cells of the rows 6 and 7
private void button1_Click(object sender, EventArgs e)
{
double result = 0;
foreach (DataGridViewCell cell in dataGridView1.SelectedCells)
{
result = result + double.Parse(cell.Value.ToString());
}
label2.Text = result.ToString();
}
and with TryParse if you want to go on the safe side:
private void button1_Click(object sender, EventArgs e)
{
double result = 0;
double nextNumber = 0;
foreach (DataGridViewCell cell in dataGridView1.SelectedCells)
{
if (double.TryParse(cell.Value.ToString(), out result))
{
nextNumber += result;
label2.Text = nextNumber.ToString();
}
}
}

Select next highlighted row in a gridview

Here is my current code:
private void searchBtn_Click(object sender, EventArgs e)
{
//get the search term from the textbox
String searchTerm = textBox.Text;
//if the column index is 1 the we search by code and 2 if we search by name
int columnIndex = 0;
if (codeRadioBtn.Checked)
columnIndex = 1;
else
columnIndex = 2;
gridView.ClearSelection();
int firstIndex = 0;
bool found = false;
for (int i = 0; i < gridView.Rows.Count; i++)
{
//change background color to DarkOrange for the rows that contain the searched value
if (gridView.Rows[i].Cells[columnIndex].Value.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase))
{
//gridView.Rows[i].Selected = true;
gridView.Rows[i].DefaultCellStyle.BackColor = Color.DarkOrange;
found = true;
if (firstIndex < 1)
{
firstIndex = i;
}
}
}
//display message if no item was found
if (!found)
MessageBox.Show("The search term was not found", "Warning");
else
// scroll grid to first highlighted row
this.gridView.Rows[firstIndex].Cells[0].Selected = true;
this.gridView.CurrentCell = this.gridView.Rows[firstIndex].Cells[0];
this.gridView.FirstDisplayedCell = this.gridView.CurrentCell;
}
I am trying to make it, onClick of the search button a second time it will set the current selected to the next highlighted row.
I have been trying for a while and can't figure it out. Any help would be greatly appreciated.
Use a List or Array to store all matches.
List<int> matchList = new List<int>();
e.g.
Whilst you are highlighting the rows, why not also add that row into a list.
gridView.Rows[i].DefaultCellStyle.BackColor = Color.DarkOrange;
matchList.add(i);
To work out whether it is the first click i.e. to load and highlight matches set a int outside of the button click to keep track of how many times you clicked the button.
int clickcount= 0;
Then after you have found and highlighted set clickcount to 1 and make sure you don't highlight again using an if statement, but instead run the below loop.
if (clickcount != 0 && clickcount !=matchList.Count-1)
{
this.gridView.CurrentCell = this.gridView.Rows[clickcount].Cells[0];
clickcount++;
}
else
{
clickcount = 0;
}
Full Example
int clickcount = 0;
List<int> matchList = new List<int>();
protected void searchBtn_Click(object sender, EventArgs e)
{
if (clickcount == 0)
{
//get the search term from the textbox
String searchTerm = textBox.Text;
//if the column index is 1 the we search by code and 2 if we search by name
int columnIndex = 0;
if (codeRadioBtn.Checked)
columnIndex = 1;
else
columnIndex = 2;
gridView.ClearSelection();
int firstIndex = 0;
bool found = false;
for (int i = 0; i < gridView.Rows.Count; i++)
{
//change background color to DarkOrange for the rows that contain the searched value
if (gridView.Rows[i].Cells[columnIndex].Value.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase))
{
//gridView.Rows[i].Selected = true;
this.gridView.CurrentCell = gridView.Rows[0].Cells[0];
gridView.Rows[i].DefaultCellStyle.BackColor = Color.DarkOrange;
matchList.Add(i);
found = true;
if (firstIndex < 1)
{
firstIndex = i;
}
}
}
//display message if no item was found
if (!found)
{
MessageBox.Show("The search term was not found", "Warning");
}
//add one to the count to stop the search happing again.
clickcount = 1;
}
else
{
//if clickcount = 1+ or your've reached the end of your match list count
if (clickcount != 0 && clickcount != matchList.Count - 1)
{
//gridView.Rows[clickcount].DefaultCellStyle.BackColor = Color.Red;
this.gridView.CurrentCell = gridView.Rows[matchList[clickcount]].Cells[0];
clickcount++;
}
else
{
MessageBox.Show("No More Found");
clickcount = 0;
matchList.Clear();
}
}
}

Highlight all searched words

In my RichtextBox, if I have written as below.
This is my pen,
his pen is beautiful.
Now I search word "is" then
output would be as below.
All "is" should be highlighted.
What about:
static class Utility {
public static void HighlightText(this RichTextBox myRtb, string word, Color color) {
if (word == string.Empty)
return;
int s_start = myRtb.SelectionStart, startIndex = 0, index;
while((index = myRtb.Text.IndexOf(word, startIndex)) != -1) {
myRtb.Select(index, word.Length);
myRtb.SelectionColor = color;
startIndex = index + word.Length;
}
myRtb.SelectionStart = s_start;
myRtb.SelectionLength = 0;
myRtb.SelectionColor = Color.Black;
}
}
Looks like this would do it.
http://www.dotnetcurry.com/ShowArticle.aspx?ID=146
int start = 0;
int indexOfSearchText = 0;
private void btnFind_Click(object sender, EventArgs e)
{
int startindex = 0;
if(txtSearch.Text.Length > 0)
startindex = FindMyText(txtSearch.Text.Trim(), start, rtb.Text.Length);
// If string was found in the RichTextBox, highlight it
if (startindex >= 0)
{
// Set the highlight color as red
rtb.SelectionColor = Color.Red;
// Find the end index. End Index = number of characters in textbox
int endindex = txtSearch.Text.Length;
// Highlight the search string
rtb.Select(startindex, endindex);
// mark the start position after the position of
// last search string
start = startindex + endindex;
}
}
public int FindMyText(string txtToSearch, int searchStart, int searchEnd)
{
// Unselect the previously searched string
if (searchStart > 0 && searchEnd > 0 && indexOfSearchText >= 0)
{
rtb.Undo();
}
// Set the return value to -1 by default.
int retVal = -1;
// A valid starting index should be specified.
// if indexOfSearchText = -1, the end of search
if (searchStart >= 0 && indexOfSearchText >=0)
{
// A valid ending index
if (searchEnd > searchStart || searchEnd == -1)
{
// Find the position of search string in RichTextBox
indexOfSearchText = rtb.Find(txtToSearch, searchStart, searchEnd, RichTextBoxFinds.None);
// Determine whether the text was found in richTextBox1.
if (indexOfSearchText != -1)
{
// Return the index to the specified search text.
retVal = indexOfSearchText;
}
}
}
return retVal;
}
// Reset the richtextbox when user changes the search string
private void textBox1_TextChanged(object sender, EventArgs e)
{
start = 0;
indexOfSearchText = 0;
}
This will show all the searched criteria at the same time.
Using: 1 Textbox (to enter the text to search for) and 1 Button (to Run the Search).
Enter your search criteria inside the textbox and press search button.
// On Search Button Click: RichTextBox ("rtb") will display all the words inside the document
private void btn_Search_Click(object sender, EventArgs e)
{
try
{
if (rtb.Text != string.Empty)
{// if the ritchtextbox is not empty; highlight the search criteria
int index = 0;
String temp = rtb.Text;
rtb.Text = "";
rtb.Text = temp;
while (index < rtb.Text.LastIndexOf(txt_Search.Text))
{
rtb.Find(txt_Search.Text, index, rtb.TextLength, RichTextBoxFinds.None);
rtb.SelectionBackColor = Color.Yellow;
index = rtb.Text.IndexOf(txt_Search.Text, index) + 1;
rtb.Select();
}
}
}
catch (Exception ex) { MessageBox.Show(ex.Message, "Error"); }
}
}
}
If you only want to match the whole word you can use this, note that this ignores case and also the |s\b means that plurals get highlighted e.g. Cat matches cats but not caterpiller :
public static void HighlightText(RichTextBox myRtb, string word, Color color)
{
if (word == string.Empty)
return;
var reg = new Regex(#"\b" + word + #"(\b|s\b)",RegexOptions.IgnoreCase);
foreach (Match match in reg.Matches(myRtb.Text))
{
myRtb.Select(match.Index, match.Length);
myRtb.SelectionColor = color;
}
myRtb.SelectionLength = 0;
myRtb.SelectionColor = Color.Black;
}
private void button3_Click(object sender, EventArgs e)
{
if (textBox1.Text != "")
{
for (int i = 0; i < richTextBox1.TextLength; i++)
{
richTextBox1.Find(textBox1.Text, i, RichTextBoxFinds.None);
richTextBox1.SelectionBackColor = Color.Red;
}
}
else
{
for (int i = 0; i < richTextBox1.TextLength; i++)
{
richTextBox1.SelectAll();
richTextBox1.SelectionBackColor = Color.White;
}
}
}[lets make it!][1]
I would do it like that because all the other answers highlight the text, but doesnt change it back after you searched again.
Use the RichText Find Method to find the starting index for the searching word.
public int FindMyText(string searchText, int searchStart, int searchEnd)
{
int returnValue = -1;
if (searchText.Length > 0 && searchStart >= 0)
{
if (searchEnd > searchStart || searchEnd == -1)
{
int indexToText = richTextBox1.Find(searchText, searchStart, searchEnd, RichTextBoxFinds.MatchCase);
if (indexToText >= 0)
{
returnValue = indexToText;
}
}
}
return returnValue;
}
Use a Button or TextChangeListener and Search for your word.
private void button1_Click(object sender, EventArgs e)
{
// Select the first char in your Richtextbox
richTextBox1.SelectionStart = 0;
richTextBox1.SelectionLength = richTextBox1.TextLength;
// Select until the end
richTextBox1.SelectionColor = Color.Black;
// Make the Text Color black
//Use an Inputfield to add the searching word
var word = txtSearch.Text;
//verify the minimum length otherwise it may freeze if you dont have text inside
if (word.Length > 3)
{
int s_start = richTextBox1.SelectionStart, startIndex = 0, index;
while ((index = FindMyText(word, startIndex, richTextBox1.TextLength)) != -1)
{
// goes through all possible found words and color them blue (starting index to end)
richTextBox1.Select(index, word.Length);
richTextBox1.SelectionColor = Color.Blue;
startIndex = index + word.Length;
}
// Color everything between in color black to highlight only found words
richTextBox1.SelectionStart = startIndex;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = Color.Black;
}
}
I would highly recommend to set a minimum word length to avoid freezing and high memory allocation.

Categories