WPF中,控件(Control)一词的意义,比早期Windows编程的控件,有更特定的含义。
比方说,在WinForms应用程序中,屏幕上出现的一切,都被视为控件。在WPF中,这个词保留给用户交互使用,也就是说,当用户用鼠标或是键盘时,控件一般会对用户提供某种响应(feedback)。前章的TextBlock、Image和Shape元素,都会接收键盘、但是它们都选择忽略,控件会主动监视并处理用户的输入。
Control 类直接继承自 FrameworkElement:
Object
DispatcherObject(abstract)
DependencyObject
Visual(abstract)
UIElement
FrameworkElement
Control
Window 继承自Control,中间还有个ContentControl,你自己知道ContentControl继承自Control,Control是继承自FrameworkElement。Control所定义的property包括Background、BorderBrush、BorderThickness以及和font相关的property,例如FontWeight和FontStretch。(注意的是:虽然TextBlock也具有许多font property,但是TextBlock不是继承自Control。TextBlock的这些property是自己定义的。)
从Control继承而来的类超过了50个,这些类提供给程序员各式各样的控件,包括按钮、列表框(list box)、滚动条(scroll bar)、编辑框(edit field)、菜单(menu)和工具条(toolbar)。这些类都是放在System.Windows.Controls与System.Windows.Controls.Primitives命名空间中的。这些命名空间也包含一些不是继承自Control的类。
最为经典的控件是Button按钮,在WPF中是Button类。Button类有一个Content 的property以及一个名为Click的事件。当用户用鼠标按下按钮,就会发生事件。
实例程序 - 1
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace PartFour
{
class ClickTheButton : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new ClickTheButton());
}
public ClickTheButton()
{
Title = " Click the Button " ;
Button btn = new Button();
btn.Content = " _Click me, please! " ;
btn.Click += new RoutedEventHandler(btn_Click);
btn.Margin = new Thickness( 100 );
btn.Height = 300 ;
btn.Width = 300 ;
btn.HorizontalContentAlignment = HorizontalAlignment.Left;
btn.VerticalContentAlignment = VerticalAlignment.Bottom;
btn.HorizontalAlignment = HorizontalAlignment.Left;
btn.VerticalAlignment = VerticalAlignment.Bottom;
Content = btn;
SizeToContent = SizeToContent.WidthAndHeight;
}
void btn_Click( object sender, RoutedEventArgs e)
{
MessageBox.Show( " The button has been Clicked and all is well. " , Title);
}
}
}
Button有一个Content property,这一点和Window一样,且并非巧合。这两个类(以及一些其他的类)都是继承自ContentControl的类,也就是定义了Content property的地方。
下面是Control以下的局部类层次图:
Control
ContentControl
ButtonBase(abstract)
Button
Window
Window与Button否有相同的 Content property.
btn.IsDefault = true; 等价于 btn.Focus();按钮作为默认按钮,也就是焦点。
或则让它可以对Escape键有反应,做法如下: btn.IsCancel = true;
实例程序 - 2:
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace PartFour
{
public class FormatTheButton : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new FormatTheButton());
}
Run runButton;
public FormatTheButton()
{
Title = " Format the Button " ;
// 建立一个按钮,将其设置成窗体的Content
Button btn = new Button();
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.VerticalAlignment = VerticalAlignment.Center;
btn.MouseEnter += new System.Windows.Input.MouseEventHandler(btn_MouseEnter);
btn.MouseLeave += new System.Windows.Input.MouseEventHandler(btn_MouseLeave);
Content = btn;
// 建立一个Textblock,将它设置成按钮的内容
TextBlock txtblk = new TextBlock();
txtblk.FontSize = 24 ;
txtblk.TextAlignment = TextAlignment.Center;
btn.Content = txtblk;
// 在TextBlock中加入格式文本
txtblk.Inlines.Add( new Italic( new Run( " Click " )));
txtblk.Inlines.Add( " the " );
txtblk.Inlines.Add(runButton = new Run( " Button " ));
txtblk.Inlines.Add( new LineBreak());
txtblk.Inlines.Add( " to launch the " );
txtblk.Inlines.Add( new Bold( new Run( " rocket " )));
}
void btn_MouseLeave( object sender, System.Windows.Input.MouseEventArgs e)
{
runButton.Foreground = Brushes.Red;
}
void btn_MouseEnter( object sender, System.Windows.Input.MouseEventArgs e)
{
runButton.Foreground = SystemColors.ControlTextBrush;
}
}
}
注意,在该程序中,包含单词"button"的Run对象被存储在一个名为runButton的变量中,当鼠标进入按钮区域时,Run对象的前景色上红色。当鼠标离开按钮区域时,颜色恢复默认值(SystemColors。ControlTextBrush)。
实例程序 - 3:
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
using System.Windows.Media;
namespace PartFour
{
public class ImageTheButton : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new ImageTheButton());
}
public ImageTheButton()
{
Title = " Image the Button " ;
Uri uri = new Uri( @" D:/MyFace.jpg " );
BitmapImage bitmap = new BitmapImage(uri);
Image img = new Image();
img.Source = bitmap;
img.Stretch = Stretch.None;
Button btn = new Button();
btn.Content = img;
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.VerticalAlignment = VerticalAlignment.Center;
Content = btn;
}
}
}
-----
Command property,ButtonBase类和其他的类(包括MenuItem)定义了这个property,对于常见的命名,你会将Button的Command property设置为ApplicationCommands、ComponentCommands、MediaCommands、NavigationCommads或EditingCommands类的静态property。前面4个类属于System.Windows.Input命名空间;后面一个是在System.Windows.Documents命名空间。这些类的静态property是属于RoutedUICommand类型。你可以创建你自己的RoutedUICommand类型的对象。
比方说,如果你想要特定的按钮,以进行一个Paste命名,你可以将Command property设置成:
btn.Command = ApplicationCommands.Paste;
现在,你需要将此特定的Paste命令与事件处理器关联起来。这样的关联方法称为绑定(binding),这是WPF数种binding中的一种.UIElement类定义一个名为CommandBindings(复数)的Property(且Control和Window类继承此property),这是CommanBinding对象的集合(collection)。你可能用窗口的CommandBinding集合:
CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste), PasteOnExecute, PasteCanExecute));
具体可参加如下程序:
实例程序 - 4:
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace PartFour
{
public class CommandTheButton : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new CommandTheButton());
}
public CommandTheButton()
{
Title = " Command The Button! " ;
// 建立按钮,并将其设置成窗体的内容
Button btn = new Button();
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.VerticalAlignment = VerticalAlignment.Center;
btn.Command = ApplicationCommands.Paste;
btn.Content = ApplicationCommands.Paste.Text;
Content = btn;
// 将此命令绑定到事件处理器
CommandBindings.Add( new CommandBinding(ApplicationCommands.Paste, PasteOnExecute, PasteCanExecute));
}
void PasteOnExecute( object sender, ExecutedRoutedEventArgs ards)
{
Title = Clipboard.GetText();
}
void PasteCanExecute( object sender, CanExecuteRoutedEventArgs args)
{
args.CanExecute = Clipboard.ContainsText();
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
base .OnMouseDown(e);
Title = " Command The Button! " ;
}
}
}
-------
切换按钮,CheckBox和RadioButton都被认为是"切换"(toggle)按钮,这一点从它们的继承结构就可以轻易看出来:
Control
ContentControl
ButtonBase(abstract)
Button
GridViewColumnHeader
RequestButton
ToggleButton
CheckBox
RadioButton
ToggleButton不是抽象类,所以你可以创建它的对象。它看起来就像一个常规的按钮,不同之处在于,他可以有On和Off切换。
实例程序 - 5:
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls.Primitives;
namespace PartFour
{
public class ToggleTheButton : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new ToggleTheButton());
}
public ToggleTheButton()
{
Title = " ToggleTheButton " ;
ToggleButton btn = new ToggleButton();
btn.Content = " Can_Resize " ;
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.VerticalAlignment = VerticalAlignment.Center;
btn.IsChecked = (ResizeMode == ResizeMode.CanResize);
btn.Checked += new RoutedEventHandler(btn_Checked);
btn.Unchecked += new RoutedEventHandler(btn_Checked);
Content = btn;
}
void btn_Checked( object sender, RoutedEventArgs e)
{
ToggleButton btn = sender as ToggleButton;
ResizeMode = ( bool )btn.IsChecked ? ResizeMode.CanResize : ResizeMode.NoResize;
}
}
}
见下面程序:
实例程序 - 6:
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media.Imaging;
namespace PartFour
{
public class BindTheButton : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new BindTheButton());
}
public BindTheButton()
{
Title = " Bind the Button ! " ;
Topmost = true ;
ToggleButton btn = new ToggleButton();
btn.Content = " Make_Topmost " ;
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.VerticalAlignment = VerticalAlignment.Center;
btn.SetBinding(ToggleButton.IsCheckedProperty, " Topmost " );
btn.DataContext = this ;
Content = btn;
// Binding bind = new Binding("Topmost");
// bind.Source = this;
// btn.SetBinding(ToggleButton.IsCheckedProperty, bind);
// 这个Binding类让你在定义数据绑定时有更过的选择
Uri uri = new Uri( @" D:/MyFace.jpg " );
BitmapImage bitmap = new BitmapImage(uri);
Image img = new Image();
img.Source = bitmap;
ToolTip tip = new ToolTip();
tip.Content = img; // "Toogle the button on to make the window topmost on the desktop";
btn.ToolTip = tip;
}
}
}
-----
TextBox控件:
Control
TextBoxBase(abstract)
TextBox
RichTextBox
实例程序 - 7:
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace PartFour
{
class UriDialog : Window
{
TextBox txtbox;
public UriDialog()
{
Title = " Enter a URI " ;
ShowInTaskbar = false ;
SizeToContent = SizeToContent.WidthAndHeight;
WindowStyle = WindowStyle.ToolWindow;
WindowStartupLocation = WindowStartupLocation.CenterOwner;
txtbox = new TextBox();
txtbox.Margin = new Thickness( 48 );
Content = txtbox;
txtbox.Focus();
}
public string Text
{
set {
txtbox.Text = value;
txtbox.SelectionStart = txtbox.Text.Length;
}
get {
return txtbox.Text;
}
}
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Enter)
Close();
}
}
class NavigateTheWeb : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new NavigateTheWeb ());
}
Frame frm;
public NavigateTheWeb()
{
Title = " Navigate the Web " ;
frm = new Frame();
Content = frm;
Loaded += new RoutedEventHandler(NavigateTheWeb_Loaded);
}
void NavigateTheWeb_Loaded( object sender, RoutedEventArgs e)
{
UriDialog dlg = new UriDialog();
dlg.Owner = this ;
dlg.Text = " http:// " ;
dlg.ShowDialog();
try
{
frm.Source = new Uri(dlg.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, Title);
}
}
}
}
实例程序 - 8:
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.IO;
using System.Windows.Controls;
using System.Windows.Input;
namespace PartFour
{
class EditSomeText : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new EditSomeText());
}
static string strFileName = @" D:/EditSomeText.txt " ;
// Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "EditSomeText/EditSomeText.txt");
TextBox txtbox;
public EditSomeText()
{
Title = " Edit Some Text " ;
// 建立 text box
txtbox = new TextBox();
txtbox.AcceptsReturn = true ;
txtbox.TextWrapping = TextWrapping.Wrap;
txtbox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
txtbox.KeyDown += new System.Windows.Input.KeyEventHandler(txtbox_KeyDown);
Content = txtbox;
try
{
txtbox.Text = File.ReadAllText(strFileName);
}
catch
{
}
txtbox.CaretIndex = txtbox.Text.Length;
txtbox.Focus();
}
void txtbox_KeyDown( object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.F5)
{
txtbox.SelectedText = DateTime.Now.ToString();
txtbox.CaretIndex = txtbox.SelectionStart + txtbox.SelectionLength;
}
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
try
{
Directory.CreateDirectory(Path.GetDirectoryName(strFileName));
File.WriteAllText(strFileName, txtbox.Text);
}
catch (Exception ex)
{
MessageBoxResult result = MessageBox.Show( " sffss " + ex.Message, Title, MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
e.Cancel = (result == MessageBoxResult.No);
}
}
}
}