Store word index in TextSelectionChanged

I have the next and previous search function and edited so that when the user selects text in the text box and clicks the Find Next or Find Previous button, the search function will start indexing at the selected character and navigate through each search result (originally the function was not). To get the starting index of the selected text, I created a function:

private int GetIntialCharPos(string Text)
{
    int row = Variables._TextBox.GetLineIndexFromCharacterIndex(Variables._TextBox.CaretIndex);
    int col = Variables._TextBox.CaretIndex - Variables._TextBox.GetCharacterIndexFromLineIndex(row);
    return col;
}

      

A function that searches for next and previous looks like this:

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<int>();
            while (startIndex < Variables._TextBox.Text.Length && (matchIndex = Variables._TextBox.Text.IndexOf(textToFind, startIndex, mode)) >= 0)
            {
                _matches.Add(matchIndex);
                startIndex = matchIndex + textToFind.Length;
            }

            _textToFind = textToFind;
            _matchCase = matchCase;
            _matchIndex = forward ? _matches.IndexOf(GetIntialCharPos(textToFind)) : _matches.IndexOf(GetIntialCharPos(textToFind)) - 1;
        }
        else
        {
            _matchIndex += forward ? 1 : -1;
            if (_matchIndex < 0)
            {
                _matchIndex = _matches.Count - 1;
            }
            else if (_matchIndex >= _matches.Count)
            {
                _matchIndex = 0;
            }
        }

        if (_matches.Count > 0)
        {
            Variables._TextBox.SelectionStart = _matches[_matchIndex];
            Variables._TextBox.SelectionLength = textToFind.Length;
            Variables._TextBox.Focus();
        }
    }

      

My problem is that once the user has selected the text he needs to find and goes through the next and previous search buttons and then he decides to select the text from a different index rather than continue searching from the selected index, it will maintain the initial order the default which it executes, not starting at the selected index and going through each result. I created a small video gif here so that you can take a better look at this issue.

How to keep the selected index of the word, so every time the user selects from a different index, it can start the search from the index where the user selects, and not always from the beginning.

+3


source to share


1 answer


private int _matchIndex;

      

It's your problem. It keeps the last hit index, but you don't know when the user changes it himself. The TextBox class does not have a SelectionChanged event to tell you this, so there is no easy way to reset a variable.

Just use RichTextBox instead, this event .



But it's much easier, this error happened because you added unnecessary state by splitting the search operation into a separate class. The condition is generally bad, it is an error generator. You can trivially make the whole operation stateless by using the TextBox object directly:

    private static void MoveToNextMatch(TextBoxBase box, bool forward) {
        var needle = box.SelectedText;
        var haystack = box.Text;
        int index = box.SelectionStart;
        if (forward) {
            index = haystack.IndexOf(needle, index + 1);
            if (index < 0) index = haystack.IndexOf(needle, 0);
        }
        else {
            if (index == 0) index = -1;
            else index = haystack.LastIndexOf(needle, index - 1);
            if (index < 0) index = haystack.LastIndexOf(needle, haystack.Length - 1);
        }
        if (index >= 0) {
            box.SelectionStart = index;
            box.SelectionLength = needle.Length;
        }
        box.Focus();
    }

      

Use the Last / IndexOf () method, which takes a StringComparison parameter to implement the matchCase argument.

+3


source







All Articles