具有智能感知功能的富文本框
本文通过扩展 RichTextBox,向您展示一个具有智能感知的 RichTextBox 的演示,它最像 Visual Studio,一个强大的 IDE。此自定义控件使您可以更轻松地将智能感知添加到项目中。
引言
几天前,我开发了一个小型应用程序,其中有一个小功能,可以根据用户的输入弹出一个列表,这非常像 Visual Studio IDE。这是一个很酷的功能,可以使您的应用程序更加用户友好。我提取了代码片段,然后通过扩展 RichTextBox
类构建了一个自定义控件,并向其添加了一些依赖属性,现在您可以在您的项目中使用此自定义控件,轻松添加智能感知。
最终结果如下

如何使用控件
好的,让我们先谈谈如何使用这个自定义控件。通过这个控件向你的 richtext box 添加智能感知非常简单。稍后您可以在文章中看到,我向自定义 richtextbox
添加了两个属性,分别是 ContentAssistSource
和 ContentAssistTriggers
。让我们先看看 XAML 代码
<rabbit:RichTextBoxEx Name="richTextBoxEx1"
AutoAddWhiteSpaceAfterTriggered="{Binding IsChecked,ElementName=chkAutoAddWhitespace}"
ContentAssistTriggers="{Binding ContentAssistTriggers}"
ContentAssistSource="{Binding ContentAssistSource}" />
是不是非常简单,对吧? 你只需要将两个属性绑定到代码隐藏中的 List,第一个是 ContentAssistTriggers
,它是字符列表,当用户将 char
类型输入到富文本框时,会触发智能感知,第二个是 ContentAssistSource
,它将用于智能感知的项目。
如何实现智能感知
智能感知如何在这里实现?首先,我们需要向自定义控件添加一个 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(<a href="mailto:'@'">'@'</a>);
}
(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
添加了一些事件,例如 PreviewKeyDown
和 MouseDoubleClick
,实际上,它们处理了智能感知弹出时用户的输入。您可以在我的源代码中的 Event 中找到我所做的事情。
然后,其次,我们应该覆盖 RichTextBox
的 OnTextInput
方法,该方法将在用户向富文本框输入字符时被调用。在此方法中,我们检查用户是否已输入触发字符,如果为 true
,我们将弹出智能感知,实际上是将 ListBox
的可见性设置为 Visible
。正如您在以下代码片段中看到的那样,我们不仅显示 ListBox
,还根据用户的输入过滤内容辅助源,然后将 ListBox
的 Itemsource
设置为过滤后的列表。
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();
}
}
第三,我们应该重写方法 OnPreviewKeyDown
。在此方法中,我们检查用户是否按了 Enter、Space 或 Tab,如果他们按下了这些键并且内容辅助 listbox
可见,则将选定的项目(实际上是 string
)插入到富文本框中。
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 - 1, 1);
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);
}
到现在为止,我们的自定义富文本框已经具有智能感知的能力。你一定注意到了
我调用了一个名为 FilterAssistBoxItemsSource
的方法,是的,它是帮助显示智能感知的最重要的方法之一。 看看代码
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;
}
}
历史
- 2011 年 4 月 12 日:首次发布