WPF制作的一个小功能,智能提示(IntelliSense)
原文http://www.cnblogs.com/scheshan/archive/2012/06/30/2570867.html
最近WPF项目中遇到一个需求,需要给一个RichTextBox添加智能提示(IntelliSense)功能。
分析下具体的需求,在用户键入"@"符号时,应该显示一个弹出框,把所有用户列出。用户可以通过键盘、鼠标等进行选择。用户列表可能数据比较多,那么用户还应该可以输入字符进行筛选。用过各种IDE开发工具的童鞋应该对这样的效果很了解了,具体效果如下
输入@符号的效果:
筛选的效果:
再谈谈具体的开发思路.
1.如何制作可以实现列表选择功能的弹出框
方法很多,Popup+ListBox可以完美解决.此处我为了省代码,直接用的ListBox
2.如何在键入@符号时,将ListBox显示在@符号之后
在VisualStudio的智能提示里,当我们触发了IntelliSense时,提示框会显示,并且与下一字符的插入点对齐。TextPointer类提供了方法可以获取到某个插入点的坐标:
RichTextBox textbox = this.RichTextBox;
TextPointer start = textbox.Selection.Start;
Rect rect = start.GetCharacterRect(LogicalDirection.Forward);
Point point = rect.BottomLeft;
我们可以注册RichTextBox的键盘事件,判断用户是否键入@符号。@符号是由“Shift”+“2”组成,Keyboard.Modifiers可以获取到组合键:
if (Keyboard.Modifiers == ModifierKeys.Shift && e.Key == Key.D2)
{
//TODO: 用户键入了@符号
}
在TODO里,将ListBox移动到得到Point位置即可。
3.如何实现选择和筛选
筛选功能很简单,保存一个局部变量,在智能提示框显示后记录用户输入,智能提示框隐藏后清空,智能提示框中的数据按照该变量进行过滤即可。
当智能提示框显示的时候,用户是可以键入“上”,“下”键进行移动选择的。也许在敲了几次方向键,用户还想继续输入字符进行筛选。最开始,我是 用的ListBox自动的选择功能,当用户敲入方向键,我就将键盘焦点(WPF中分键盘焦点和逻辑焦点,这个也是困扰我很久的问题)设置到ListBox 上,那么用户就可以敲入“上”,“下”键进行移动选择了。看起来很简单,但是这样是有问题的,因为用户如果想继续敲入字符筛选,我还必须将键盘焦点重新设 置到RichTextBox上,否则用户的敲击是无效的。
后来突然想通了,在用户敲击“上”,“下”键时,只需要调用ListBox的MoveCurrentToPrevious()和 MoveCurrentToNext()即可,这样给用户的错觉还是有了上下移动的效果。焦点不在ListBox上时,这样的移动可能造成当前选中项超出 了显示范围之外,那么可以通过ListBox的ScrollIntoView()方法,将选中对象滚动到视图中。
下面是截取的一段代码:

//如果按了向下键,则把选中项下移
if (e.Key == Key.Down)
{
if (UserList.CurrentPosition != UserList.Count - )
{
lbUser.Items.MoveCurrentToNext();
lbUser.ScrollIntoView(lbUser.Items.CurrentItem);
}
e.Handled = true;
}
//如果按了向上键,则把选中项上移
if (e.Key == Key.Up)
{
if (UserList.CurrentPosition != )
{
lbUser.Items.MoveCurrentToPrevious();
lbUser.ScrollIntoView(lbUser.Items.CurrentItem);
}
e.Handled = true;
}

4.实现选中和取消
选中功能就更简单了,分别加入对鼠标双击,空格,回车,TAB等的判断,将ListBox的当前选中项的文本插入到
RichTextBox中即可。需要注意的是,此处要对单击做判定,由于单击ListBox会使键盘焦点设置到其之上,因此要强制将键盘焦点从
ListBox移开。判断ESC键,使ListBox隐藏即可实现取消功能。
5.如何实现扩展
做一个功能最重要的就是考虑以后的重用,此处可以公开
KeyBoard.Modifyers,KeyCode,IEnumable<T>为依赖属性,前2个代表在敲入什么组合键时会弹出智能提示
框,最后一个是弹出内容的数据源。由于此处的筛选功能是在控件内部,那么我们可以定义一个接口,包含一个Name属性。
public interface IData
{
//用于筛选和插入的名称
string Name { get; set; }
}
将上面的IEnumable<T>改为IEnumable<IData>。
以后的调用方,只需要将这3个中的一个或多个传入,即可实现智能提示功能。
WPF制作的一个小功能,智能提示(IntelliSense)的更多相关文章
- 在VS中让一个JS文件智能提示另一个JS文件中的成员
“在VS中如何让一个JS文件智能提示另一个JS文件中的成员” 有时候会有这种情况:当我的一个Web页面引用了两个JS文件(假如分别叫common.js和JScript1.js),如果JScript1. ...
- 模仿京东顶部搜索条效果制作的一个小demo
最近模仿京东顶部搜索条效果制作的一个小demo,特贴到这里,今后如果有用到可以参考一下,代码如下 #define kScreenWidth [UIScreen mainScreen].bounds.s ...
- 用MVC5+EF6+WebApi 做一个小功能(三) 项目搭建
一般一个项目开始之前都会有启动会,需求交底等等,其中会有一个环节,大讲特讲项目的意义,然后取一个高大上的项目名字,咱这是一个小功能谈不上项目,但是名字不能太小气了.好吧,就叫Trump吧.没有任何含义 ...
- Visual Studio中让一个JS文件智能提示另一个JS文件中的成员
当一个Web页面引用了两个JS文件(假如分别叫common.js和JScript1.js),如果JScript1.js中需要调用大量的common.js中的方法,这时候在JScript1.js中智能提 ...
- 用MVC5+EF6+WebApi 做一个小功能(四) 项目分层功能以及文件夹命名
在上一节,我们完成了一个项目搭建,我们看到的是一个项目的分层架子,那接下来每一层做什么以及需要引用哪些内容呢?在本节内容我们还逐步拆分每一层的功能,顺带添加package包 Trump.Domain ...
- 用MVC5+EF6+WebApi 做一个小功能(二) 项目需求整理
在一个项目开始前,需求整理大概要占到整个项目周期15%甚至30%的比重,可以说需求理得越清楚,后续开发中返工几率越小.在一个项目中,开发新功能的花费的精力要远远小于修改功能的精力,这基本是一个共识.老 ...
- 在VS中让一个JS文件智能提示另一个JS文件中的成员2--具体引用
我们知道,在html中,利用<script language="javascript" type="text/javascript" src=" ...
- 空闲时间研究一个小功能:winform桌面程序如何实现动态更换桌面图标
今天休息在家,由于天气热再加上疫情原因,就在家里呆着,空闲时想着,在很早以前(约3年前),产品人员跟我提了一个需求,那就是winform桌面程序的图标能否根据节日动态更换,这种需求在移动APP上还是比 ...
- 【一个小功能】点击图标/链接发起QQ临时会话
有时候,我们需要实现在网页上点击一个QQ图标来实现QQ临时会话,这样不用添加好友,也能满足及时沟通的需求. 实现方案比较简单,只是为a标签修改href属性,代码如下 <a href=" ...
随机推荐
- 编程是一项需要时间来掌握的技能(Anders的经验)
Anders现在每天仍然花大量的时间实际写代码,并且未来会一直写下去.他很清醒的知道自己长处:“相比起管理,我还是更擅长于编程.” 事实上,Anders的成名之作Turbo Pascal通过出售软件授 ...
- linux下awk命令详解
简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...
- jsp中全局变量和局部变量的设置
- IO队列和IO调度
IO体系概览 先看看本文主题IO调度和IO队列处于整个IO体系的哪个位置,这个IO体系是非常重要的,了解IO体系我们可以对整个IO过程有个全面的认识.虽然一下两下并不清楚IO体系各个部分的细节,但是我 ...
- SpringMVC(二)——流程控制
SpringMVC主要就是用来做流程控制的,这篇博客总结一下如何在流程控制添加Interceptor(拦截器),如何将进行流程Mapping映射解析,如何编写Controller(控制器). 一,首先 ...
- JS~重写alter与confirm,让它们变成fancybox风格
插件与系统命令 对于很多JS弹框插件来说,都提供了alter,confirm等功能,如fancybox,Boxy等插件,今天来介绍一下如何将系统的alter和confirm替换成指定插件的alter和 ...
- shadow projection
1.概述 shadow projection,又可成为planar shadow, 这是一种非常简单的绘制阴影的方法. 主要应用的应用场景:物体在平面投射阴影. 主要思想:把阴影看作是物体在平面上的投 ...
- 《JavaScript 闯关记》之基本包装类型
为了便于操作基本类型值,JavaScript 还提供了3个特殊的引用类型:Boolean.Number 和 String.实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象 ...
- MySQL的字符串函数截取字符
函数: 1.从左开始截取字符串 left(str, length) 说明:left(被截取字段,截取长度) 例:select left(content,200) as abstract from my ...
- WCF入门教程系列三
一.WCF服务应用程序与WCF服务库 我们在平时开发的过程中常用的项目类型有“WCF 服务应用程序”和“WCF服务库”. WCF服务应用程序,是一个可以执行的程序,它有独立的进程,WCF服务类契约的定 ...