Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Search Through a text Window app crash

Tags:

c#

wpf

c#-4.0

I have two methods which search through a text document in my WPF app. When search for a word in the first search it works fine, but when I add a word to it, it will crash and come up with a null exception. Can someone please help?

Crashes on:

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

Stacktrace:

{"Value cannot be null.\r\nParameter name: position2"}

Example:

if the text said this.

And I search for "if the", then I search for "if the text said" it would crash.

        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;
        }
like image 955
Robert Avatar asked Mar 04 '26 08:03

Robert


1 Answers

  1. Method GetPositionAtOffset can return null if it cannot find this position. See TextPointer.GetPositionAtOffset. In your case you see it because you do the search until you don't reach end of your search range, but in the case when for example your search range contains 100 symbols and your search text has 10 symbols after you reach pointer at index 91 - you will call GetPositionAtOffset with offset 10 - and this will be 101 symbol, which gives you null in this case.
  2. You can do simple check in your for loops, something like:

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

    You have one more similar for loop, just add this special check in it too.

  3. It looks like you are doing search, so just want to give you two recommendations:

    • Use string.Compare method instead ToLower. See String.Compare Method (String, String, Boolean, CultureInfo). In your case it should be string.Compare(text1, text2, ignoreCase: true, culture: CultureInfo.CurrentCulture). In this case your application will support all languages.
    • If you really want to use ToLower and do search in this way - consider to change it to ToUpper, because some languages can be tricky when you do ToLower. Check this article What's Wrong With Turkey?. When you do ToLower(I) with Turkish locale you will get dotless i, which is different from i. Wikipedia about: Dotted and dotless I.
like image 195
outcoldman Avatar answered Mar 05 '26 21:03

outcoldman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!