• 增加智能感知的RichTextBox扩展控件(WPF)


     

    简介

    闲来无事,写篇博客打发时间。前几日想给WPF的RichTextBox新增上智能感知的功能,搜了一圈没有找到合适的开源代码,于是自己花了点时间搞定了它,小小的扩展了一下RichTextBox,先看效果图:

    intellisense_rich_text_box.png

    怎么使用这个扩展后的RichTextBox

    扩展后的RTB新增了几个依赖属性:

    ContentAssistSource:智能感知数据源

    ContentAssistTriggers:智能感知触发器(即当输入哪些字符时会显示智能感知)

    AutoAddWhiteSpaceAfterTriggered:当选择提示中的某一项时,是否自动增加空格

    可以直接在xaml中这样使用:

    <rabbit:RichTextBoxEx Name="richTextBoxEx1"
    AutoAddWhiteSpaceAfterTriggered
    ="{Binding IsChecked,ElementName=chkAutoAddWhitespace}"
    ContentAssistTriggers
    ="{Binding ContentAssistTriggers}"
    ContentAssistSource
    ="{Binding ContentAssistSource}" />

    很简单吧?

    如何实现的?

    一、准备

    为了实现这一功能,我首先在扩展后的rtb中添加一个ListBox,作为智能提示数据源的载体。在rtb 加载后将ListBox添加到它的父容器中(为了方便控制位置,此处强制父容器为Grid),如下代码片断:

     private ListBox AssistListBox = new ListBox();
    void RichTextBoxEx_Loaded(object sender, RoutedEventArgs e)
               {
                   
    //init the assist list box
                   if (this.Parent.GetType() != typeof(Grid))
                   {
                       
    throw new Exception("this control must be put in Grid control");
                   }

                   
    if (ContentAssistTriggers.Count == 0)
                   {
                       ContentAssistTriggers.Add(
    '@');
                   }

                   (
    this.Parent as Grid).Children.Add(AssistListBox);
                   AssistListBox.MaxHeight 
    = 100;
                   AssistListBox.MinWidth 
    = 100;
                   AssistListBox.HorizontalAlignment 
    = System.Windows.HorizontalAlignment.Left;
                   AssistListBox.VerticalAlignment 
    = System.Windows.VerticalAlignment.Top;
                   AssistListBox.Visibility 
    = System.Windows.Visibility.Collapsed;
                   AssistListBox.MouseDoubleClick 
    += new MouseButtonEventHandler(AssistListBox_MouseDoubleClick);
                   AssistListBox.PreviewKeyDown 
    += new KeyEventHandler(AssistListBox_PreviewKeyDown);
               }

    你看到了,我给ListBox新增了MouseDoubleClick 和PreviewKeyDown 事件,就是为了方便用户选择提示的内容。事件中都做了哪些事件呢?就是简单的将当前选中的Item的值插入到RichTextbox中。在此不贴代码了。

    二、如何显示

    做完准备工作后,如何在用户输入某些特定的字母后,出现对应的提示呢?

    其实也挺简单,重写一下OnTextInput事件,在该事件里做一些判断,如果满足出现提示的条件,就把ListBox给显示到合适的位置,同时再做一些其他的工作,就ok了:

    protected override void OnTextInput(System.Windows.Input.TextCompositionEventArgs e)
               {
                   
    base.OnTextInput(e);
                   
    if (IsAssistKeyPressed == false && e.Text.Length == 1)
                   {
                       
    if (ContentAssistTriggers.Contains(char.Parse(e.Text)))
                       {
                           ResetAssistListBoxLocation();
                           IsAssistKeyPressed 
    = true;
                           FilterAssistBoxItemsSource();
                           
    return;
                       }
                   }

                   
    if (IsAssistKeyPressed)
                   {
                       sbLastWords.Append(e.Text);
                       FilterAssistBoxItemsSource();
                   }
               }

    接下来再override一个OnPreviewKeyDown事件,处理一下用户的按键事件,比如当用户按下enter或tab时,就表明用户想选择当前的第一项,当按下Down键时,意味着用户想选择下一项等等,如下代码所示:

     
    protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
               {
                   
    if (!IsAssistKeyPressed)
                   {
                       
    base.OnPreviewKeyDown(e);
                       
    return;
                   }

                   ResetAssistListBoxLocation();

                   
    if (e.Key == System.Windows.Input.Key.Back)
                   {
                       
    if (sbLastWords.Length > 0)
                       {
                           sbLastWords.Remove(sbLastWords.Length 
    - 11);
                           FilterAssistBoxItemsSource();
                       }
                       
    else
                       {
                           IsAssistKeyPressed 
    = false;
                           sbLastWords.Clear();
                           AssistListBox.Visibility 
    = System.Windows.Visibility.Collapsed;
                       }
                   }

                   
    //enter key pressed, insert the first item to richtextbox
                   if ((e.Key == Key.Enter || e.Key == Key.Space || e.Key == Key.Tab))
                   {
                       AssistListBox.SelectedIndex 
    = 0;
                       
    if (InsertAssistWord())
                       {
                           e.Handled 
    = true;
                       }
                   }

                   
    if (e.Key == Key.Down)
                   {
                       AssistListBox.Focus();
                   }

                   
    base.OnPreviewKeyDown(e);
               }

    到现在为止,扩展的richtextbox已经具备了智能感知的功能。上面的几个代码块中都用到了一个方法,FilterAssistBoxItemsSource(),它是负责ListBox的显示或是隐藏的:

    private void FilterAssistBoxItemsSource()
               {
                   IEnumerable
    <string> temp = ContentAssistSource.Where(s => s.ToUpper().StartsWith(sbLastWords.ToString().ToUpper()));
                   AssistListBox.ItemsSource 
    = temp;
                   AssistListBox.SelectedIndex 
    = 0;
                   
    if (temp.Count() == 0)
                   {
                       AssistListBox.Visibility 
    = System.Windows.Visibility.Collapsed;
                   }
                   
    else
                   {
                       AssistListBox.Visibility 
    = System.Windows.Visibility.Visible;
                   }
               }
    有感兴趣的,就下载下来演示看看。感觉到对自己的项目有用的,就下下来源码看看。如果觉得不符合自己的需求,就改改。
  • 下载演示- 9.39 KB
  • 下载源码 - 22.12 KB
  • 相关阅读:
    Chrome V75V76新版无法存为mhtml格式解决办法
    RHEL7 的注册
    JQuery淡入淡出 banner切换特效
    怎样把小坚果做成大生意
    黄页前台联动菜单修改时不能显示,要重新选择|没样式
    V9任何页面GET调用内容分页的说明
    phpcms v9 自定义伪静态的分页函数
    phpcms v9 自定义分页 带下拉跳转
    discuz X2.5自己写代码,获取当前登录的用户信息
    discuz!X2.5技术文档
  • 原文地址:https://www.cnblogs.com/hanxianlong/p/2018433.html
Copyright © 2020-2023  润新知