Because TextBox doesn't have a find function, I've created and modified my own version of it to my needs. I've created to functions. One for Search Next and another for Search Previous
My problem is that:
If my search term is more than 1 character long and I've searched for the term four times, IF on the 4th term I decide the click on search previous it goes back to the previous search term and that works fine. Now because I clicked on search previous 4 times and I went to the 3rd search term using previous, IF I decide to go the 4th term again using Find Next, I have to double click on find next and then it selects the 4th term.
If my search term is 1 character long and I want to search for a character, I type the character e.g. 'o' and it goes through each character in the textbox but once I decide to go back using search previous, I have to double click search previous button and then it goes back and if I decide to search next I have to double click again then it searches next.
This might help understand the double click and single click:
http://media.giphy.com/media/3xz2BJgF2DrtcCnP1e/giphy.gif
I've been trying to get this to work for quite a while now and I've had no luck. I have no idea where I'm going with this and before I confuse myself it will be great if someone can help me with this.
My code for:
Variables
public int startPostion = 0;
boolean passedNext;
public int pos = 0;
Search Next
public bool FindAndSelectNext(string TextToFind, bool MatchCase)
{
try
{
var mode = MatchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
int position = TheTextBox.Text.IndexOf(TextToFind, startPostion, mode);
pos = position;
if (position == -1)
{
var TheString = TheTextBox.Text;
var foundposition2 = TheString.IndexOf(TextToFind, mode);
TheTextBox.SelectionStart = foundposition2;
TheTextBox.SelectionLength = TextToFind.Length;
startPostion = foundposition2 + TextToFind.Length;
TheTextBox.Focus();
passedNext = false;
Debug.WriteLine("1");
return true;
}
else
{
TheTextBox.SelectionStart = position;
TheTextBox.SelectionLength = TextToFind.Length;
startPostion = position + TextToFind.Length;
TheTextBox.Focus();
passedNext = true;
Debug.WriteLine("2");
return true;
}
}
catch (Exception ex)
{
MessageBox.Show(string.Format("Could not find '{0}' in the document.", TextToFind), ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
return true;
}
Search Previous
public bool FindAndSelectPrevious(string TextToFind, bool MatchCase)
{
StringComparison mode = MatchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
if (passedNext == true)
{
int foundPosition = startPostion < 0 ? TheTextBox.Text.Length : startPostion - 1;
foundPosition = TheTextBox.Text.LastIndexOf(TextToFind, pos, mode);
passedNext = false;
if (foundPosition < 0)
{
if (startPostion < 0)
{
MessageBox.Show(string.Format("Could not find '{0}' in the document.", TextToFind), ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
foundPosition = TheTextBox.Text.LastIndexOf(TextToFind, mode);
Debug.WriteLine("1p");
}
TheTextBox.SelectionStart = foundPosition;
TheTextBox.SelectionLength = TextToFind.Length;
startPostion = foundPosition;
TheTextBox.Focus();
Debug.WriteLine("2p");
passedNext = false;
}
else
{
int foundPosition = startPostion < 0 ? TheTextBox.Text.Length : startPostion;
foundPosition = TheTextBox.Text.LastIndexOf(TextToFind, foundPosition, mode);
if (foundPosition < 0)
{
if (startPostion < 0)
{
MessageBox.Show(string.Format("Could not find '{0}' in the document.", TextToFind), ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
foundPosition = TheTextBox.Text.LastIndexOf(TextToFind, mode);
}
if (!(foundPosition == -1))
{
try
{
int foundPositionz = startPostion < 0 ? TheTextBox.Text.Length : startPostion - 1;
foundPositionz = TheTextBox.Text.LastIndexOf(TextToFind, foundPositionz, mode);
TheTextBox.SelectionStart = foundPositionz;
TheTextBox.SelectionLength = TextToFind.Length;
startPostion = foundPositionz;
TheTextBox.Focus();
}
catch (Exception ex)
{
var TheString = TheTextBox.Text;
var foundposition2 = TheString.LastIndexOf(TextToFind, mode);
TheTextBox.SelectionStart = foundposition2;
TheTextBox.SelectionLength = TextToFind.Length;
startPostion = foundposition2;
TheTextBox.Focus();
Debug.WriteLine("12p");
}
}
else
{
MessageBox.Show(string.Format("Could not find '{0}' in the document.", TextToFind), ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
return true;
}
IMHO, you should just find all the matches the first time the user tries to find something, and then keep an index indicating which match is to be selected/highlighted.
For example:
private List<int> _matches;
private string _textToFind;
private bool _matchCase;
private int _matchIndex;
private void MoveToNextMatch(string textToFind, bool matchCase, bool forward)
{
if (_matches == null ||
_textToFind != textToFind ||
_matchCase != matchCase)
{
int startIndex = 0, matchIndex;
StringComparison mode = matchCase ?
StringComparison.CurrentCulture :
StringComparison.CurrentCultureIgnoreCase;
_matches = new List();
while (startIndex < TheTextBox.Text.Length &&
(matchIndex = TheTextBox.Text.IndexOf(textToFind, startIndex, mode)) >= 0)
{
_matches.Add(matchIndex);
startIndex = matchIndex + textToFind.Length;
}
_textToFind = textToFind;
_matchCase = matchCase;
_matchIndex = forward ? 0 : _matches.Count - 1;
}
else
{
_matchIndex += forward ? 1 : -1;
if (_matchIndex < 0)
{
_matchIndex = _matches.Count - 1;
}
else if (_matchIndex >= _matches.Count)
{
_matchIndex = 0;
}
}
if (_matches.Count > 0)
{
TheTextBox.SelectionStart = _matches[_matchIndex];
TheTextBox.SelectionLength = textToFind.Length;
TheTextBox.Focus();
}
else
{
MessageBox.Show(string.Format(
"Could not find '{0}' in the document.", TextToFind),
ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
public bool FindAndSelectNext(string textToFind, bool matchCase)
{
MoveToNextMatch(textToFind, matchCase, true);
}
public bool FindAndSelectPrevious(string textToFind, bool matchCase)
{
MoveToNextMatch(textToFind, matchCase, false);
}