RichTextBox with text filtering

好久不见. 提交于 2020-03-06 04:52:06

问题


How can I implement in richTextBox something like filter (connected e.g. with combobox) that'll be responsible for showing only lines containing selected word (filters)?

I'm not talking about removing other lines - only "hide".

Is it possible?

Eventually I could use another type control, but if it's not neccessary I'd like to use richTextBox.

I thought now, about storing data in some structure, and make filtering based on this used structure. But don't know if it's efficient solution.


回答1:


Try to make something like this

    public string[] RtbFullText;

    private void button7_Click(object sender, EventArgs e)
    {
        RtbFullText = richTextBox1.Text.Split('\n');
    }

    private void button8_Click(object sender, EventArgs e)
    {
        //Filter
        richTextBox1.Text = "";
        foreach (string _s in RtbFullText)
        {
            if (_s.Contains("Filter"))
                richTextBox1.Text += _s + "\n";
        }
    }



回答2:


So you can do this

public class NewRichTextBox : RichTextBox
{
    public string[] TotalText;
    private bool filter = false;
    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        if (!filter)
            TotalText = Text.Split('\n');
    }
    public void Filter(string sf)
    {
        filter = true;
        Text = "";
        foreach (string _s in TotalText)
        {
            if (_s.Contains(sf))
                Text += _s + "\n";
        }
        filter = false;
    }
}

    public Form1()
    {
        InitializeComponent();
        NewRichTextBox myrtb = new NewRichTextBox();
        myrtb.Name = "NRTB";
        Controls.Add(myrtb);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        NewRichTextBox mtrb = (NewRichTextBox)Controls.Find("NRTB", false)[0];
        mtrb.Filter("Filter");
    }



回答3:


OMG i do it, use this class:

    public class ListWithRTB : IList
    {
        private List<string> _contents = new List<string>();
        private int _count;
        string lastsearch = "";

        public ListWithRTB()
        {
            _count = 0;
        }

        public object rtb;

        private void UpdateRtb(string search)
        {
            lastsearch = search;
            if (rtb is RichTextBox)
            {
                ((RichTextBox)rtb).Text = "";
                List<string> help_contents;
                if (search != "")
                    help_contents = _contents.Where(s => s.Contains(search)).ToList();
                else
                    help_contents = _contents;
                for (int i = 0; i < help_contents.Count; i++)
                {
                    ((RichTextBox)rtb).Text += help_contents[i] + "\n";
                }
            }
        }

        public void Filter(string search)
        {
            UpdateRtb(search);
        }

        public int Add(object value)
        {
            if (_count < _contents.Count + 1)
            {
                _contents.Add((string)value);
                _count++;
                UpdateRtb(lastsearch);
                return (_count);
            }
            else
            {
                return -1;
            }
        }

        public void RemoveAt(int index)
        {
            _contents.RemoveAt(index);
            _count--;
            UpdateRtb(lastsearch);
        }

        public void Clear()
        {
            _contents.Clear();
            UpdateRtb(lastsearch);
            _count = 0;
        }

        public bool Contains(object value)
        {
            return _contents.Contains((string)value);
        }

        public int IndexOf(object value)
        {
            return _contents.IndexOf((string)value);
        }

        public void Insert(int index, object value)
        {
            _contents.Insert(index,(string) value);
            _count++;
        }

        public bool IsFixedSize
        {
            get
            {
                return false;
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public void Remove(object value)
        {
            RemoveAt(IndexOf(value));
        }

        public object this[int index]
        {
            get
            {
                return _contents[index];
            }
            set
            {
                _contents[index] = value.ToString();
            }
        }

        public void CopyTo(Array array, int index)
        {
            int j = index;
            for (int i = 0; i < Count; i++)
            {
                array.SetValue(_contents[i], j);
                j++;
            }
        }

        public int Count
        {
            get
            {
                return _count;
            }
        }

        public bool IsSynchronized
        {
            get
            {
                return false;
            }
        }

        public object SyncRoot
        {
            get
            {
                return this;
            }
        }

        public IEnumerator GetEnumerator()
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void PrintContents()
        {
            Console.WriteLine("List has a capacity of {0} and currently has {1} elements.", _contents.Count, _count);
            Console.Write("List contents:");
            for (int i = 0; i < Count; i++)
            {
                Console.Write(" {0}", _contents[i]);
            }
            Console.WriteLine();
        }

    }

And this how you can use it

ListWithRTB _mlrtb = new ListWithRTB();

    private void button1_Click(object sender, EventArgs e)
    {
        _mlrtb.rtb = richTextBox1;
        _mlrtb.Add("Filter");
        _mlrtb.Add("123");
        _mlrtb.Add("111 Filter");
    }

    private void button2_Click(object sender, EventArgs e)
    {
        _mlrtb.Filter("Filter");
    }

    private void button3_Click(object sender, EventArgs e)
    {
        _mlrtb.Filter("");
    }



回答4:


 private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (!string.IsNullOrEmpty(SearchableString) && !string.IsNullOrEmpty(FullRichtxt))
        {
            var SplitedTxt = FullRichtxt.Split('\n').ToList<string>();
            List<string> filterlist = SplitedTxt.Where(x => x.Contains(contx.SearchableString)).ToList<string>();
            string FilterString=string.Empty;
            foreach(string str in filterlist)
            {
                FilterString+=str+"\n";
            }
           (RichTextBox1 as  RichTextBox).AppendText(FilterString);
        }
    }



回答5:


I know this has been a very old question however I ran into the same issue and implemented it which also retains any RTF formatting.

    /// <summary>
    /// This Control allows to filter the content of the RichTextBox by either manually
    /// calling <c>ApplyFilter(string)</c> with the search string or specifying a TextBox Control
    /// as a filter reference. 
    /// 
    /// Matching lines will be retained, other will be deleted.
    /// 
    /// Retains RTF formatting and when removing the filter restores the original content.
    /// 
    /// Ideal for a Debug Console.
    /// 
    /// </summary>
    public class RichFilterableTextBox : RichTextBox
    {
        private Timer timer;
        private string OriginalRTF = null;
        private TextBox _filterReference;
        private int _interval = 2000;

        public TextBox FilterReference
        {
            get => _filterReference;
            set
            {
                //if we had already a filter reference
                if (_filterReference != null)
                {
                    //we should remove the event
                    _filterReference.TextChanged -= FilterChanged;
                }

                _filterReference = value;

                //if our new filter reference is not null we need to register our event
                if (_filterReference != null)
                    _filterReference.TextChanged += FilterChanged;
            }
        }

        /// <summary>
        /// After the filter has been entered into the FilerReference TextBox 
        /// this will auto apply the filter once the interval has been passed.
        /// </summary>
        public int Interval
        {
            get => _interval;
            set
            {
                _interval = value;
                timer.Interval = Interval;
            }
        }
        public RichFilterableTextBox()
        {
            timer = new Timer();
            timer.Interval = Interval;
            timer.Tick += TimerIntervalTrigger;
        }

        public void SetFilterControl(TextBox textbox)
        {
            this.FilterReference = textbox;
        }

        public void ApplyFilter(string searchstring)
        {
            int startIndex = 0;
            int offset = 0;

            //check each line
            foreach (var line in this.Lines)
            {
                offset = 0;
                SelectionStart = startIndex + offset;
                SelectionLength = line.Length + 1;

                //if our line contains our search string/filter
                if (line.Contains(searchstring))
                {
                    //we apply an offset based on the line length
                    offset = line.Length;
                }
                else
                {
                    //otherwise delete the line
                    SelectedText = "";
                }

                //move the start index forward based on the current selected text
                startIndex += this.SelectedText.Length;
            }
        }

        private void FilterChanged(object sender, EventArgs e)
        {
            //take snapshot of original
            if (OriginalRTF == null)
            {
                OriginalRTF = this.Rtf;
            }
            else
            {
                //restore original
                Rtf = OriginalRTF;
                OriginalRTF = null;
            }

            timer.Stop();
            timer.Start();
        }
        private void TimerIntervalTrigger(object sender, EventArgs e)
        {
            //stop the timer to avoid multiple triggers
            timer.Stop();

            //apply the filter
            ApplyFilter(FilterReference.Text);
        }
        protected override void Dispose(bool disposing)
        {
            timer.Stop();
            timer.Dispose();

            base.Dispose(disposing);
        }
    }

This control can be either used standalone and be filter by calling the method ApplyFilter(string searchString) with the desired search string. Or it can be connected to a TextBox where you will be able to enter the phrase in. After a set timer interval it will auto trigger the filtering.

I am using this as a Log Display during runtime where I am also applying color codes to severity and my goal was to retain the formatting as well as be able to quickly search/filter. I attached a few screenshots:

There is still room for improvements and I hope this can be used as a starting code base.



来源:https://stackoverflow.com/questions/10188933/richtextbox-with-text-filtering

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!