说明:本系列基本上是《WPF揭秘》的读书笔记。在结构安排与文章内容上参照《WPF揭秘》的编排,对内容进行了总结并加入一些个人理解。
文本与墨水控件用来显示与编辑文字。
TextBox (WPF/Silverlight 2.0)
TextBox控件使用户能够输入一行或多行文字。TextBox中输入的内容存储在一个叫Text的字符串属性(string类型)中。要是TextBox支持多行输入,需要给TextBox指定一个高度,或在在没有指定高度的情况下放入一个指定了高度的容器,另外将AcceptsReturn属性为true以允许TextBox接受回车输入。当TextBox接收到回车输入时会在文本中插入一个'\r'。
TextBox绑定了多种命令包括Cut,Copy,Paste,Undo与Redo。
TextBox可以支持拼写检查,方式是将SpellCheck.IsEnabled属性设置为True。TextBox拼写检查的体验类似Office Word,支持的语言由系统所装语言包决定。另外可以使用于TextBlock相同的方式给TextBox的内容设置字体。
TextBox的属性
TextBox的事件
TextBox对单行下显示与换行以及多行显示的支持
TextBox宽度除非受周围内容所限或者被指定的值固定,否则TextBox会随着输入文字的增加而逐渐增加(就如一种被撑开的效果)。当TextBox宽度被限制时可以使用如下属性来处理:
TextWrapping:当值为Wrap时,可以将文字形成新的换行,其不允许有任何一行超过文字的边界。当被设置为WrapWithOverflow时,TextBox仅会保留一行,长文字会被截断。
通过将AcceptReturn设置为true可以实现在输入时使用回车来换行。如果通过编程设置给TextBox的字符串包括Text.NewLine这样的字符,则TextBox会换行显示且与AcceptReturn属性无关。
RichTextBox(WPF)
RichTextBox可以支持格式化的文字。RichTextBox与TextBox共有相同的TextBoxBase基类,所以像是TextBox的拼写检查等特性RichTextBox以相同的方式支持。
RichTextBox的属性
PasswordBox (WPF)
PasswordBox是一种设计目的简单的TextBox控件 ,就是用于输入密码。其将输入的文字显示为小圆点(PasswordChar属性提供你更改这种显示的途径),从而保护信息。
PasswordBox不继承自TextBoxBase,所以其不支持除Paste外那些普通TextBox支持的命令,当然更不支持拼写检查。
PasswordBox中输入的值被存储于Password属性中,内部这个值使用System.Security.SecureString类型的对象保存,不同于一般的string,这个对象不会被GC置于托管堆中一段时间,而是会被强行清空。
PasswordBox的事件
InkCanvas(WPF)
从技术上讲,InkCanvas不是一种控件而是一种元素,它直接由FrameworkElement继承。其行为与控件类似,但是不能通过新的模版改变其样式。InkCanvas用来捕获鼠标或触笔的笔记并绘制在InkCanvas表面。当使用触笔时,笔尖用来写,而另一端用来擦除。
InkCanvas的属性:
下面介绍三个InkCanvasEditingMode类型的属性:
以上三个属性均为InkCanvasEditingMode类型,可能的值有如下几种:
当InkCanvas的容器设置为SizeToContent时,如果绘制超出当前边界的内容,容易会自动变大,以适应其中的内容。
WatermarkedTextBox(Silverlight 2.0)
在一些好的界面设计中,我们常会看到文本框中有一些淡淡的提示文字告诉用户应该在这输入什么内容,而当用户开始输入时这些提示就会消失,在Silverlight中使用WatermarkedTextBox可以帮助你轻松实现这个效果。WatermarkedTextBox的使用几乎与TextBox一致,除了你可以通过Watermark属性创建一个简单的水印,另外Watermark属性还是一个内容属性,也就是说可以在水印中放入其他XAML所支持的内容 – 如图片或视频等。
下面代码通过属性元素的语法为WatermarkedTextBox指定了一个复杂的填充水印。
1 <WatermarkedTextBox Width="240"> 2 <WatermarkedTextBox.Watermark> 3 <StackPanel> 4 <Ellipse Width="20" Fill="Azure"></Ellipse> 5 <TextBlock Text="我是测试用的"></TextBlock> 6 <Rectangle Width="50" Height="30"></Rectangle> 7 </StackPanel> 8 </WatermarkedTextBox.Watermark> 9 </WatermarkedTextBox>
提示:
将TextBlock控件的Foreground属性设置为LightGray也可以模拟出类似的水印效果。
InkPresenter控件
通过对Ink的支持,Silverlight将笔输入的功能带入到富Web中。常见的笔输入设备包括:手写笔,触摸屏及传统的鼠标设备。首先我们来看一下支持Ink特性的一些类。每次输入设备划过屏幕时,会生成一个或多个StylusPoint对象,这些对象保存在StylusPointCollection集合中,形成了基本的笔划。这些笔划(StylusPointCollection)又保存在StrokeCollection中组成一组图案。它们可以通过InkPresenter显示出来(InkPresenter是Canvas的子类),同时这些类都提供了属性与方法以供编程操作它们的对象。下面我们详细介绍下这些类及其中提供的方法与属性:
StrokeCollection类型
InkPresenter对象的Strokes集合属性接收StrokeCollection的实例,StroekCollection集合按顺序保存了用户输入的笔画。
属性:
方法:
Stroke类型
StrokeCollection是Stroke对象组成的集合。一个Stroke对象是一个组成该笔划的点的有序集合,这里笔划是一次独立的动作记录:由笔尖按下,笔尖移动至笔尖抬起。
属性:
方法:
StylusPointCollection类型
该集合包含一组StylusPoint对象,主要用于保存笔划的点集合。(有时候,也可以作为参数传递给HitTest方法,以判断犹如笔划相交)
属性
方法:
StylusPoint类型
StylusPoint代表一个单一的点。
属性:
Ink相关事件
输入设备的产生的事件按鼠标事件被处理,事件参数为MouseEventArgs类型。该类型提供了如下属性和方法用来查询或处理输入信息,输入设备等。(MoseEnter,MouseLeave,MouseLeftButtonDown,MouseLeftButtonUp和MouseMove事件接收相同的MouseEventArgs对象)
属性:
方法:
我们可以使用JavaScript或C# 来操作这些类及其对象,首先我们看一下使用JavaScript捕获用户输入并通过InkPresenter展示的方法:
第一步我们需要初始化一些基本的对象:
1 var theInk; //Ink Presenter 2 var stroke; // a Stroke 3 var slCtrl; // Silverlight control 4 function handleLoad(control, userContext, rootElement) { 5 slCtrl = control; 6 theInk = control.content.findName("inkPr"); 7 }
一切就绪,我们开始由MouseLeftButtonDown事件开始一步步展示捕获过程。
1 function inkMouseDown(sender, args) { 2 theInk.CaptureMouse(); 3 stroke = slCtrl.content.createFromXaml('<stroke/>'); //create stroke 4 var da = slCtrl.content.createFromXaml('<DrawingAttributes/>'); 5 stroke.DrawingAttributes = da; 6 stroke.DrawingAttributes.Width = 2; 7 stroke.DrawingAttributes.Height = 2; 8 stroke.DrawingAttributes.Color = "White"; 9 stroke.DrawingAttributes.OutlineColor = "White"; 10 //add styluspoint to stroke 11 stroke.StylusPoints.AddStylusPoints(args.GetStylusPoints(theInk)); 12 //add stroke to inkpresenter 13 theInk.Strokes.add(stroke); 14 }
上面方法中,我们开始捕获鼠标并定义了表示线条样式的DrawingAttributes对象,接下来处理鼠标的移动,这个过程中记录鼠标的轨迹并绘制在InkPresenter中:
1 function inkMouseMove(sender, args) { 2 if (stroke != null) { 3 stroke.StylusPoints.AddStylusPoints(args.GetStylusPoints(theInk)); 4 } 5 }
最后,我们处理鼠标抬起事件,我们清空stroke,这样鼠标移动的点信息不会再添加到笔划中:
1 function inkMouseUp(sender, args) { 2 stroke = null; 3 theInk.releaseMouseCapture(); 4 }
看过了JavaScript的示例,接着我们给出一段使用C#实现这个效果的代码:
1 Stroke newStroke; 2 private void inkEl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 3 { 4 inkEl.CaptureMouse(); 5 // Create a new stroke. 6 newStroke = new Stroke(); 7 DrawingAttributes da = new DrawingAttributes(); 8 newStroke.DrawingAttributes = da; 9 newStroke.DrawingAttributes.Width=2; 10 newStroke.DrawingAttributes.Height=2; 11 newStroke.DrawingAttributes.Color=Colors.White; 12 newStroke.DrawingAttributes.OutlineColor=Colors.White; 13 newStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkEl)); 14 inkEl.Strokes.Add(newStroke); 15 } 16 private void inkEl_MouseMove(object sender, MouseEventArgs e) 17 { 18 if (newStroke != null) 19 { 20 newStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkEl)); 21 } 22 23 } 24 private void inkEl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 25 { 26 newStroke = null; 27 inkEl.ReleaseMouseCapture(); 28 }