3

我有两种方法可以在我的 WPF 应用程序中搜索文本文档。在第一次搜索中搜索单词时,它可以正常工作,但是当我向其中添加单词时,它会崩溃并出现空异常。有人可以帮忙吗?

崩溃:

TextRange result = new TextRange(start, start.GetPositionAtOffset(searchText.Length));

堆栈跟踪:

{"值不能为空。\r\n参数名称:位置 2"}

例子:

如果文字这么说。

然后我搜索“如果”,然后搜索“如果文本说”它会崩溃。

        private void btnSearch_Click(object sender, RoutedEventArgs e)
        {
            string searchText = searchBox.Text.Trim();
            searchText = searchText.ToLower();

            if (String.IsNullOrWhiteSpace(searchText))
            {
                MessageBox.Show("Please enter a search term!");
                searchBox.Clear();
                searchBox.Focus();
                newSearch = true;
                return;
            }

            if (!String.IsNullOrEmpty(lastSearch))
                {
                if (lastSearch != searchText)
                    newSearch = true;
            }

            TextRange searchRange;

            RichTextBox _body = ((DockPanel)((TabItem)tabControl.Items[tabControl.SelectedIndex]).Content).Children[1] as RichTextBox;
            _body.Focus();

            if (newSearch)
            {
                searchRange = new TextRange(_body.Document.ContentStart, _body.Document.ContentEnd);
                lastSearch = searchText;
                TextPointer position2 = _body.Document.ContentEnd;
            }

            else
            {
                backupSearchRange = new TextRange(_body.CaretPosition.GetLineStartPosition(1) == null ?
                    _body.CaretPosition.GetLineStartPosition(0) : _body.CaretPosition.GetLineStartPosition(1), _body.Document.ContentEnd);



                TextPointer position1 = _body.Selection.Start.GetPositionAtOffset(1);
                TextPointer position2 = _body.Document.ContentEnd;

                searchRange = new TextRange(position1, position2);
            }

            TextRange foundRange = newSearchFunction(searchRange, searchText);

            if (foundRange == null)
            {
                if (newSearch)
                {
                    MessageBox.Show("\'" + searchBox.Text.Trim() + "\' not found!");
                    newSearch = true;
                    lastOffset = -1;
                }

                else
                {
                    MessageBox.Show("No more results!");
                    newSearch = true;
                    lastOffset = -1;
                }
            }

            else
            {
                _body.Selection.Select(foundRange.Start, foundRange.End);
                _body.SelectionBrush = selectionHighlighter;
                newSearch = false;
            }
        }      

        private TextRange newSearchFunction(TextRange searchRange, string searchText)
        {
            int offset = searchRange.Text.ToLower().IndexOf(searchText);
                offset = searchRange.Text.ToLower().IndexOf(searchText);

            if (offset < 0)
                return null;

            if (lastOffset == offset)
            {
                //searchRange = backupSearchRange;

                offset = searchRange.Text.ToLower().IndexOf(searchText);

                if (offset < 0)
                    return null;

                for (TextPointer start = searchRange.Start.GetPositionAtOffset(offset); start != searchRange.End; start = start.GetPositionAtOffset(1))
                {
                    TextRange result = new TextRange(start, start.GetPositionAtOffset(searchText.Length));

                    if (result.Text.ToLower() == searchText)
                    {
                        lastOffset = offset;
                        return result;
                    }
                }

            }

            for (TextPointer start = searchRange.Start.GetPositionAtOffset(offset); start != searchRange.End; start = start.GetPositionAtOffset(1))
            {
                TextRange result = new TextRange(start, start.GetPositionAtOffset(searchText.Length));

                if (result.Text.ToLower() == searchText)
                {
                    lastOffset = offset;
                    return result;
                }
            }

            return null;
        }
4

1 回答 1

1
  1. GetPositionAtOffset如果找不到该位置,方法可以返回 null。请参阅TextPointer.GetPositionAtOffset。在您的情况下,您会看到它,因为您进行搜索直到您没有到达搜索范围的末尾,但是在例如您的搜索范围包含 100 个符号并且您的搜索文本在您到达索引 91 处的指针后有 10 个符号的情况下- 您将以GetPositionAtOffset偏移量 10 调用 - 这将是 101 符号,null在这种情况下为您提供。
  2. 您可以在for循环中进行简单的检查,例如:

    for (
        TextPointer start = searchRange.Start.GetPositionAtOffset(offset); 
        start != searchRange.End; 
        start = start.GetPositionAtOffset(1))
    {
        var end = start.GetPositionAtOffset(searchText.Length);
        if (end == null) 
        {
            break;
        }
    
        TextRange result = new TextRange(start, end);
    
        if (result.Text.ToLower() == searchText)
        {
           lastOffset = offset;
           return result;
        }
    }
    

    您还有一个类似的for循环,只需在其中添加此特殊检查即可。

  3. 看起来您正在搜索,所以只想给您两个建议:

    • 改用string.Compare方法ToLower。请参阅String.Compare Method (String, String, Boolean, CultureInfo)。在您的情况下,它应该是string.Compare(text1, text2, ignoreCase: true, culture: CultureInfo.CurrentCulture). 在这种情况下,您的应用程序将支持所有语言。
    • 如果您真的想以ToLower这种方式使用并进行搜索 - 请考虑将其更改为ToUpper,因为在执行 ToLower 时某些语言可能会很棘手。查看这篇文章土耳其怎么了?. 当您ToLower(I)使用土耳其语言环境时,您会得到dotless ii. 维基百科关于:点和无点 I
于 2013-10-22T06:18:17.393 回答