【问题标题】:Preserve word index on TextSelectionChanged在 TextSelectionChanged 上保留单词索引
【发布时间】:2015-10-09 00:48:55
【问题描述】:

我有一个查找下一个和上一个功能并对其进行了编辑,以便当用户在文本框中选择文本并单击“查找下一个”或“查找上一个”按钮时,查找功能将从所选字符开始索引并继续通过每个搜索结果(最初该功能不存在)。为了获取所选文本的起始索引,我创建了一个函数:

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

查找下一个和上一个的函数如下:

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();
        }
    }

我的问题是,一旦用户选择了他需要搜索的文本,并通过查找下一个和上一个按钮,然后他决定从不同的索引中选择文本,而不是从选定的索引中继续搜索索引,它将保持默认的初始顺序,而不是从选定的索引开始并从中遍历每个结果。我创建了一个小的gif video here,以便您更好地了解这个问题。

如何保留选定的单词索引,以便每次用户从不同的索引中选择时,它都可以从用户选择的索引开始搜索,而不是总是从头开始。

【问题讨论】:

    标签: c# search textbox selection


    【解决方案1】:
    private int _matchIndex;
    

    这是你的问题变量。它保留了最后的匹配索引,但您不知道用户何时自行更改。 TextBox 类没有一个 SelectionChanged 事件来告诉您它,因此没有简单的方法来重置变量。

    只需使用 RichTextBox,它确实有 that event

    但是更容易发生这个错误是因为您通过将搜索操作拆分到单独的类中不必要地添加了状态。状态通常是一件坏事,它是一个错误生成器。您可以通过直接使用 TextBox 对象轻松地使整个操作无状态:

        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();
        }
    

    使用采用 StringComparison 的 Last/IndexOf() 方法来实现 matchCase 参数。

    【讨论】:

    • 我正在使用 wpf 文本框,并且有一个可用的选择更改事件。但我猜这段代码会起作用,因为我假设您编写的代码不需要使用选择更改事件。我出去了,我会测试它并告诉你
    • 我将如何循环搜索结果,即当我到达特定突出显示文本的末尾时,我单击下一个或上一个,我怎样才能重新开始搜索?目前如果我继续点击下一个,它将在最后一个学期结束,如果我点击上一个,它会引发索引超出范围错误。
    • 这确实是一个错误,已修复并可以打包。
    猜你喜欢
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-05
    • 2012-06-18
    • 2020-05-17
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    相关资源
    最近更新 更多