WPF控件分类
在WPF中,控件的基类为Object,按照继承类的不同分为四类:
1.ContentControl——内容控件
继承自System.Windows.Controls.ContentControl;内建的内容控件分为3类:
1)按钮:Button、RepeatButton、ToggleButton、RadioButton、CheckBox
2)简单容器:Label、ToolTip、Frame
3)带头容器:GroupBox、Expander
2. ItemsControl——Items控件
继承自ItemsControl类,分为3类:
1)选择器:ComboBox、ListBox、ListView、TabControl
2)菜单:Menu、ContextMenu
3)其他:TreeView、ToolBar、StatusBar
3.RangeControl——范围控件
来自RangeBase抽象类,有ProgressBar和Slider
4.文本和墨水控件
TextBox、RichTextBox、PasswordBox和InkCanvas
具体到每个控件的使用以及注意事项,放到后边具体说明。
创建WPF应用程序
这一篇本应该介绍WPF控件中的内容控件,但是在这之前我还是将如何创建WPF App和如何执行简单介绍一下。如下:
1.打开VS2010,选择“文件”->新建项目,打开如下图对话框,单击Visual C#节点,选择“WPF应用程序”,填写程序对应的名称,存储位置,解决方案等,单击“确定”,项目创建完成。
2.创建成功后,你会看到一个处于打开状态下的.xaml文件,名称为MainWindow,这是程序创建后生成的默认的起始窗口。就像你创建asp.net程序生成一个Default.aspx文件一样。窗口布局分为上下两个部分,上部是设计选项卡,下部是XAML代码,当然可以互换。设计部分显示的内容就是程序load起来之后的界面布局效果,而XAML部分是可视化界面生成的代码,但不是C#代码。这种方式是不是觉得很熟悉?.aspx页面也是这样设计的。
3. 下面创建一个UI元素,两种方式实现:从工具箱直接拖动控件或是手写代码的方式,由于拖动控件时不免产生一些不必要的元素属性,同时效率并不是很高,所以我直接采用后者。在XAML中写下如图代码,这时你看到上边会有一个内容为OK的大大的button铺满窗口。
4.如何运行程序?此前WinForm中有一个Program.cs文件,可以在Main函数中new想要运行的窗口。但是在WPF中我并没有看到这样一个类文件。它是通过设置App.xaml文件根节点Application中的StartUri属性将某个窗口作为起始窗口的。当然默认的就是MainWindow.xaml,所以不用修改。按Ctrl+F5不调试运行(有异常时,加断点按F5执行)。
以上就是创建WPF应用程序,执行App的过程,期间对于xaml页有了一定认识。
WPF控件:内容控件
内容控件是只允许包含单一项(item)的简单控件。
内容控件都继承自Syste.Windows.Controls.ContentControl,它们拥有只含有一项的Object类型的Content属性。
因为内容控件的单一项可能是任一对象,所以它可能包含一个很大的对象树。它只能有一个直接子节点。除了Content外,ContentControl类另一个有趣的成员是HasContent布尔型属性。如果Content为空,返回false,反之返回true。
WPF自带的内容控件有3大类:按钮、简单容器、带头(Header)容器。(注:Window类也是一种内容控件)以下包括以后介绍的控件属性有很多,这里只是需要注意的属性。
1.按钮
1)Button
特点:最基本的Button。
属性:IsDefault=false,当前默认选中的Button。
注意:Button的Content属性,可以放置任何控件,不仅限于文本。
示例:
2)RepeatButton
特点:和普通Button不同,按钮一直被按着的情况下同样触发单击事件。
属性:Delay ——在开始重复前被按下等待的时间
Interval——开始重复后重复之间的时间间隔
注意:WPF没有内建的“上下”控件,但可以通过RepeatButton实现。
示例:
XAML:
Interval="200" Click="rBtnUp_Click" HorizontalAlignment="Right" />
Interval="500" Click="rBtnDown_Click" HorizontalAlignment="Left" VerticalAlignment="Bottom" />
C#:
private int num = 0;
public RepeatButtonTest()
{
InitializeComponent();
txtNum.Text = num.ToString();
}
//增
private void rBtnUp_Click(object sender, RoutedEventArgs e)
{
num++;
txtNum.Text = num.ToString();
//MessageBox.Show(this.rBtnUp.Delay.ToString()+"\t"+this.rBtnUp.Interval.ToString());
}
//减
private void rBtnDown_Click(object sender, RoutedEventArgs e)
{
num--;
txtNum.Text = num.ToString();
}
3)ToggleButton
特点:点击时刻保留其状态的“粘性”按钮。
属性:IsChecked两个值:true、false
IsThreeState=true时,IsChecked有3个值:true、null、false
注意:IsChecked属性值在不同情况下的变化。
示例:
XAML:
C#:
private void ToggleButton_Click(object sender, RoutedEventArgs e)
{
ToggleButton tbutton = sender as ToggleButton;
if (tbutton.IsChecked.HasValue)
MessageBox.Show("IsChecked的Value:" + tbutton.IsChecked.Value.ToString());
else
MessageBox.Show("IsChecked没有Value");
}
4)RadioButton
特点:互斥
属性:GroupName,用于分组,类型string
注意:分组名称字符串相同,即为一组。
示例:
5)CheckBox
特点:与ToggleButton只是外观差别
属性:无特别
注意:它是按钮,只因为它具有按钮的特性,只是外观不太像button而已。
示例:
2.简单容器
1)Label
特点:最基本的控件
属性:Content
注意:Content存储任何内容,但只对文本有效。
示例:
"/>
2)ToolTip
特点:存放说明性内容,可以是Image或文本等。
属性:Content
注意:必须放在赋值给另一个元素的ToolTip属性,而非直接放在元素树中。可以这样说,它必须有宿主,例如Label。
示例:
" ToolTip="说明性文字"/>
3)Frame
特点:类似HTML中的Frame。
属性:Content
注意:加载速度稍慢。
示例:
3.带头容器
带头容器的特征就是Header属性。
1)GroupBox
特点:有Header属性
属性:Header
注意:无
示例:
2)Expander
特点:可折叠
属性:Header
ExpanderDirection——Up、Down、Left、Right
IsExpanded——true(折叠)、false(展开)
事件:Expanded、Collapsed——展开、折叠时触发
示例:
WPF控件:Items控件
Items控件,从名称上不难看出它是包含诸多Item的一类控件。
Items控件继承自ItemsControl类,分为3个类型:
1.选择器
选择器(selector)作为Items 控件,它的Item 不但可以被索引而且可以被选择。Selector 抽象类继承自ItemsControl,并添加了一些属性来处理选择。例如,有3 个相似的属性可以获取或设置当前的选择:
SelectedIndex——非负的整型数,它表示哪个Item 被选择了,如果没有东西被选择,则用-1 表示。Item是根据被添加到集合中的顺序来计数的。
SelectedItem——当前被选中的Item 的实例。
SelectedValue——当前被选中的Item 的值。默认情况下这个值是Item 本身,这时SelectedValue 与SelectedItem 是一样的。通过设置SelectedValuePath 去选择任意的属性或者表达式,用来表示每个Item 的值(SelectedValuePath 与DisplayMemberPath 工作原理一样)。
所有3 个属性都是可读写的,所以可以用它们去改变当前的选择,也可以用它们得到当前的选择。WPF 有4 种继承自Selector 的控件:ComboBox、ListBox、ListView、TabControl。
1)ComboBox
特点:从列表中选择一个Item。它是一种比较流行的控件,因为它不占太多空间,选择框中只显示选择的Item。
属性:IsDropDownOpen(可读写)、SelectedValuePath、DisplayMemberPath等
事件:DropDownOpened、DropDownClosed 对应IsDropDownOpen的两种状态触发相应的事件。
注意:后台数据源绑定value,显示text时,使用的是SelectedValuePath、DisplayMemberPath,绑定方式和asp.net中绑定DropDownList的数据源类似。同样ComboBox的Items可以是任何类型,Image、Text等等。
示例:
XAML:
C#:
cbTest.DisplayMemberPath = "display"; //选择框中显示的文本
cbTest.SelectedValuePath = "value"; //选择项对应的值
cbTest.ItemsSource = source; //绑定数据源,这里和asp.net不同,没有DataSource属性,而是ItemsSource
2)ListBox
特点:支持单选和多选项的Items控件。
属性:SelectionMode——支持多选的属性,有3个值:Extended(连续多选)、Multiple(不连续多选)、Single(单选)。
注意:Header属性。
示例:VerticalAlignment="Top",布局属性,设置控件垂直方向上靠上显示。后边局部控件时具体说明。
<ListBox HorizontalAlignment="Left" VerticalAlignment="Top" SelectionMode="Extended">
<StackPanel TextSearch.Text="item1" Orientation="Horizontal" Margin="5">
<Image Source="1.bmp"/>
<StackPanel Width="80">
<TextBlock Margin="5,0" FontSize="14" FontWeight="Bold" VerticalAlignment="Center">
item1
TextBlock>
<TextBlock Margin="5" VerticalAlignment="Center" TextWrapping="Wrap">
item1详情
TextBlock>
StackPanel>
StackPanel>
<StackPanel TextSearch.Text="item2" Orientation="Horizontal" Margin="5">
<Image Source="2.bmp"/>
<StackPanel Width="80">
<TextBlock Margin="5,0" FontSize="14" FontWeight="Bold" VerticalAlignment="Center">
item2
TextBlock>
<TextBlock Margin="5" VerticalAlignment="Center" TextWrapping="Wrap">
item2详情
TextBlock>
StackPanel>
StackPanel>
ListBox>
3)ListView
特点:继承自ListBox。
示例:
<ListView>
<ListViewItem IsSelected="True">item1ListViewItem>
<ListViewItem>item2ListViewItem>
ListView>
4)TabControl
特点:默认选中第一个选项卡页。
示例:
<TabControl>
<TabItem Header="tabItem1">
<Label>Hello World!Label>
TabItem>
<TabItem Header="tabItem2">
<Label>Hello World,too!Label>
TabItem>
TabControl>
2.菜单
1)Menu
特点:菜单
示例:
<Menu VerticalAlignment="Top">
<MenuItem Header="文件(_F)">
<MenuItem Header="新建"/>
<MenuItem Header="打开"/>
<MenuItem Header="发送">
<MenuItem Header="到桌面"/>
<MenuItem Header="到Email"/>
MenuItem>
<MenuItem Header="退出"/>
MenuItem>
<MenuItem Header="编辑(_E)">
<MenuItem Header="撤销"/>
<MenuItem Header="重做"/>
<MenuItem Header="剪切"/>
MenuItem>
<MenuItem Header="视图(_V)">MenuItem>
Menu>
2)ContextMenu
特点:右键快捷菜单。
注意:必须有宿主元素,作为其附加属性存在。使用方式同上篇说到的ToolTip。
示例:
<ListBox VerticalAlignment="Top" Height="30">
<ListBoxItem>新增ListBoxItem>
<ListBox.ContextMenu>
<ContextMenu>
新增操作。。。
ContextMenu>
ListBox.ContextMenu>
ListBox>
3.其他Items控件
1)TreeView
特点:属性结构,层次清晰。
示例:
<TreeView>
<TreeViewItem Header="节点1">
<TreeViewItem Header="节点1-1"/>
<TreeViewItem Header="节点1-2"/>
TreeViewItem>
<TreeViewItem Header="节点2">
<TreeViewItem Header="节点2-1"/>
TreeViewItem>
<TreeViewItem Header="节点3">TreeViewItem>
TreeView>
2)ToolBar
特点:工具栏,通常在菜单栏下方显示。
示例:实现一个简单的文本编辑器
XAML :
<ToolBar VerticalAlignment="Top" Height="30" ToolBar.OverflowMode="AsNeeded">
<Button>
<Image Source="imgs/copy.gif"/>
Button>
<Separator/>
<ToggleButton x:Name="tbBold" Click="tbBold_Click">
<Image Source="imgs/bold.gif"/>
ToggleButton>
<ToggleButton x:Name="tbItalic" Click="tbItalic_Click">
<Image Source="imgs/italic.gif"/>
ToggleButton>
<ToggleButton x:Name="tbUnderline" Click="tbUnderline_Click">
<Image Source="imgs/underline.gif"/>
ToggleButton>
<Separator/>
<Label>ZoomLabel>
<ComboBox>
<ComboBoxItem Selector.IsSelected="True">100%ComboBoxItem>
<ComboBoxItem>50%ComboBoxItem>
<ComboBoxItem>20%ComboBoxItem>
ComboBox>
ToolBar>
<TextBlock x:Name="textBlock" VerticalAlignment="Bottom" FontSize="20">
ToolBarTest
TextBlock>
C#:
private void tbBold_Click(object sender, RoutedEventArgs e)
{
if (tbBold.IsChecked.Value == true)
textBlock.FontWeight = FontWeights.Bold;
else
textBlock.FontWeight = FontWeights.Normal;
}
private void tbItalic_Click(object sender, RoutedEventArgs e)
{
if (tbItalic.IsChecked.Value == true)
textBlock.FontStyle = FontStyles.Italic;
else
textBlock.FontStyle = FontStyles.Normal;
}
private void tbUnderline_Click(object sender, RoutedEventArgs e)
{
if (tbUnderline.IsChecked.Value == true)
textBlock.TextDecorations = TextDecorations.Underline;
else
textBlock.TextDecorations = null;
}
3)StatusBar
特点:状态栏,通常在底部显示。
示例:
<StatusBar VerticalAlignment="Bottom" Height="30">
<Label Content="状态栏"/>
<Separator/>
Zoom
<ComboBox>
<ComboBoxItem IsSelected="True">100%ComboBoxItem>
<ComboBoxItem>50%ComboBoxItem>
<ComboBoxItem>20%ComboBoxItem>
ComboBox>
<Separator/>
状态栏
StatusBar>
WPF控件:Range控件
Range控件的核心功能来自一个叫RangeBase的抽象类。这个类定义了浮点数类型的属性来存储当前的值记忆范围的端点:Value、Minimum和Maximum。还定义了一个简单的ValueChanged事件。
Range控件不会像内容或者Items控件那样渲染任何内容,它们仅在一个指定的范围内存储并且显示数值。
两个主要的内建Range控件:ProgressBar、Slider。
1.ProgressBar
特点:进度条
属性:Minimum(默认0)、Maximum(默认100)、
IsIndeterminate(为true时,控件显示一段动画)
Orientation(默认Horizontal)
示例:
<ProgressBar Width="200" Height="20" IsIndeterminate="True" />
2.Slider
特点:比ProgressBar稍微复杂一些,用户能够通过在刻度尺移动手指光标来改变当前的值。
属性:Minimum (默认0),Maximum (默认10),
Orientation (默认Horizontal)
Delay和Interval属性
TickPlacement(TopLeft、BottomRight、Both)
IsSelectionRangeEnabled(true、false)
SelectionStart和SelectionEnd支持在当前范围内显示一个更小的范围。
示例:拖动Slider的滑块,在TextBox中显示对应的值
XAML:
<Slider Name="slider"
VerticalAlignment="Top"
Orientation="Horizontal"
TickPlacement="Both"
Minimum="0" Maximum="5"
Delay="200" Interval="100"
IsSelectionRangeEnabled="True"
SelectionStart="2"
SelectionEnd="4"
ValueChanged="slider_ValueChanged"/>
<TextBox Name="txtValue" VerticalAlignment="Bottom"/>
C#:
private void slider_ValueChanged(object sender,
RoutedPropertyChangedEventArgs<double> e)
{
txtValue.Text = e.NewValue.ToString();
}
这两个控件较之TextBox等,使用频率不是太高。
WPF控件:文本和墨水控件
之所以将文本和墨水控件放到一起,并不是它们继承自同一基类,而是它们在行为上比较相同。文本控件涉及TextBox、RichTextBox和PasswordBox三个控件,墨水控件是指InkCanvas,下边一一揭晓使用方式。
1.TextBox
特点:用户能够输入一行或多行文字内容。
注意:和其他大部分WPF控件不同,内容存储为一个System.Object,而是存在一个Text的字符串属性。
属性:Text——内容存放
TextWrapping——控件宽度被限制时,设置此属性可以将文字换行形成额外的行。
其值有3个:
NoWrap(默认)、
Wrap(不允许有任何一行超过控件的边界,即使在一个字中间,也强制换行)、
WrapWithOverflow(仅保留一行,只要一有机会,长文字就被截断)
AcceptReturn——支持多行(设置为true时,可以敲Enter换行)
事件:TextChanged、SelectionChanged ——验证控件内容时可用
示例:
<TextBox TextWrapping="Wrap" Width="200" Height="50">TextBox>
2.RichTextBox
特点:富文本,一种更加高级的TextBox,它能包含格式化的文字(以及嵌在文字当中的任意对象)。与TextBox使用相同基类TextBoxBase,因此许多TextBox的特性也适用于RichTextBox,只是RichTextBox的属性更为复杂一些。
属性:Document
注意:内容存放在Document属性里,它的类型是FlowDocument,而不是一个简单的字符串。
示例:
<RichTextBox Width="200" Height="120">
<RichTextBox.Document>
<FlowDocument>
<BlockUIContainer>
<StackPanel>
<Label>RichTextBoxLabel>
<Image Source="wpf.png" Width="60" Height="60"/>
StackPanel>
BlockUIContainer>
FlowDocument>
RichTextBox.Document>
RichTextBox>
3.PasswordBox
特点:密码框,可以将内容以特殊字符显示,如*等。
注意:在asp.net中,密码框是作为TextBox的一种特殊Mode存在的,也就是设置相应的TextMode=”Password”就可以了,而在WPF中密码框是作为单一的一个控件类型存在的。
属性:Password——存储内容,PasswordChar——外观显示特殊字符
示例:
<PasswordBox Password="123" PasswordChar="*"/>
4.InkCanvas
特点:从命名来猜想,应该是类似手写的这样一个“控件”。没错,WPF有很多支持手写、触摸的属性,这些可用作移动开发,比如Windows Phone。它的主要目的是(通过鼠标或指示笔)捕捉笔迹。从技术上说它不是一个控件(从FrameworkElement继承而来),但是行为和控件非常像(但不能用一个新模板来改变样式)。
属性:EditingMode,为InkCanvasEditingMode类型,其值有几个:Ink(EditingMode默认值)、InkAndGesture、GestureOnly、EraseByStroke、EraseByPoint、Select、None。
示例:模拟简单的手写擦除。
XAML:
<InkCanvas x:Name="inkCanvas" >
<Image Source="Images/wpf.png"/>
InkCanvas>
<Button Content="橡皮" Width="60" Height="23" Click="Button_Click">
Button>
C#:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
if (btn.Content.Equals("钢笔"))
{
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
inkCanvas.DefaultDrawingAttributes.Color = Colors.Yellow;
inkCanvas.DefaultDrawingAttributes.Height = 5;
inkCanvas.DefaultDrawingAttributes.Width = 5;
inkCanvas.DefaultDrawingAttributes.FitToCurve = true;
inkCanvas.DefaultDrawingAttributes.IsHighlighter = true;
btn.Content = "橡皮";
}
else
{
inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint;
btn.Content = "钢笔";
}
}
到此,WPF的几类控件的简单使用介绍完毕。有人会问:什么时候使用什么控件?当然这需要你在使用的过程中去体会了。
布局:尺寸缩放、定位和元素变换
其实布局很好理解,无非就是把一些控件放到用户界面上,摆放合理即可。
布局这部分,既有属性又有布局控件,我将从3个方面去说明:1.尺寸缩放、定位与应用变换2.使用面板布局3.使用自定义面板布局。首先,第一部分:
1.尺寸缩放
1)Width、Height
注意:通常不显式设置Width和高度。But why?因为显式设置的Width和Height属性在不同的系统主题下可能出现不适。那如果我一定要显式设置,很好的方案就是自己写一套主题。
特殊的自动长度:NaN、Auto。
示例:其实之前的某些示例已经涉及到了,非常简单。
<Button x:Name="btn" Height="23" Width="60" Content="确定" />
2)Margin、Padding
注意:Margin控制元素边界以外的空间;Padding控制元素边界以内的空间。
都属于System.Windows.Thickness类型,Thickness类,以用来表示1、2或4个浮点值。
1个值:距4个边界值相同;
2个值:Left、Top
4个值:Left、Top、Right、Bottom
示例:
<Border Margin="50,10,0,0" Padding="50,2" Background="Blue">
<Label Content="Label"/>
(运行效果图)
3)Visibility
注意:它不是Boolean类型,而是一个有3中状态的枚举类型,其值如下:
Visible:元素获得渲染并且参与布局
Collapsed:元素不可见并且不参与布局
Hidden:元素不可见但是参与布局
示例:窗口中有4个Button,两个显示的,一个折叠,一个隐藏。
<StackPanel Background="Aqua">
<Button>1Button>
<Button Visibility="Collapsed">2Button>
<Button Visibility="Hidden">3Button>
<Button>4Button>
StackPanel>
(运行效果图)
2.定位
1)对齐
属性:HorizontalAlignment属性枚举类型值:Left、Center、Right、Stretch(可伸缩)
VerticalAlignment属性枚举类型值:Top、Center、Bottom、Stretch
示例:
<StackPanel>
<Button HorizontalAlignment="Left"
Background="AliceBlue">LeftButton>
<Button HorizontalAlignment="Center"
Background="Orange">CenterButton>
<Button HorizontalAlignment="Right" Background="Aqua">RightButton>
<Button HorizontalAlignment="Stretch"
Background="Lime">StretchButton>
StackPanel>
(运行效果图)
2)内容对齐
属性:HorizontalContentAlignment属性枚举类型值:Left、Center、Right、Stretch(可伸缩)
VerticalContentAlignment属性枚举类型值:Top、Center、Bottom、Stretch
示例:
<StackPanel>
<Button HorizontalContentAlignment="Left"
Background="AliceBlue">LeftButton>
<Button HorizontalContentAlignment="Center"
Background="Orange">CenterButton>
<Button HorizontalContentAlignment="Right"
Background="Aqua">RightButton>
<Button HorizontalContentAlignment="Stretch"
Background="Lime">StretchButton>
StackPanel>
(运行效果图)
3)流向
属性:改变元素内部流的方向,有两个值:
LeftToRight:默认,自左至右
RightToLeft:自右至左
示例:
<StackPanel>
<Button FlowDirection="LeftToRight"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Top"
Height="40" Background="AliceBlue">LeftToRightButton>
<Button FlowDirection="RightToLeft"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Top"
Height="40" Background="Orange">RightToLeftButton>
StackPanel>
(运行效果图)
3.应用变换
WPF有一些内建的2D变换类,有了应用变换,就可以改变元素的尺寸和位置,但不会收到之前属性的影响。
1)旋转——RotateTransform
属性:根据3个浮点类型属性的值来旋转元素:
Angle 旋转角度,单位为度数,默认=0
CenterX 旋转的水平中心,默认=0
CenterY 旋转地垂直中心,默认=0
默认点(CenterX,CenterY),及(0,0)表示左上角。
示例:
<StackPanel>
<Button Width="60" Height="23" Background="AliceBlue">
<TextBlock RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<RotateTransform Angle="0"/>
TextBlock.RenderTransform>
0°
TextBlock>
Button>
<Button Width="60" Height="23" Background="Orange">
<TextBlock RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<RotateTransform Angle="45"/>
TextBlock.RenderTransform>
45°
TextBlock>
Button>
<Button Background="Lime" Height="23" Width="60">
<TextBlock RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform><RotateTransform Angle="90" />
TextBlock.RenderTransform>
90°
TextBlock>
Button>
StackPanel>
(运行效果图)
2)缩放——ScaleTransform
属性:根据4个浮点类型属性的值来缩放元素:
ScaleX 元素宽度的乘数,默认=1
ScaleY 元素高度的乘数,默认=1
CenterX 水平缩放的原点,默认=0
CenterY 垂直缩放的原点,默认=0
示例:
<StackPanel Width="100">
<Button Background="AliceBlue">No ScalingButton>
<Button Background="Orange">
<Button.RenderTransform>
<ScaleTransform ScaleX="2"/>
Button.RenderTransform>
X
Button>
<Button Background="Yellow">
<Button.RenderTransform>
<ScaleTransform ScaleX="2" ScaleY="2"/>
Button.RenderTransform>
X + Y
Button>
<Button Background="Lime">
<Button.RenderTransform>
<ScaleTransform ScaleY="2"/>
Button.RenderTransform>
Y
Button>
StackPanel>
(运行效果图)
3)倾斜
属性:根据4个浮点类型属性的值来倾斜元素:
AngleX 水平倾斜的角度,默认=0
AngleY 元素高度的乘数,默认=0
CenterX 水平倾斜的原点,默认=0
CenterY 垂直倾斜的原点,默认=0
示例:
<Button Width="150" Height="30" Background="Lime">
<Button.RenderTransform>
<SkewTransform AngleX="20" AngleY="20" />
Button.RenderTransform>
AngleX=20 AngleY=20
Button>
(运行效果图)
4)移动
属性:根据2个浮点类型属性的值来移动元素:
X 水平移动量,默认=0
Y 垂直移动量,默认=0
示例:
<Button Width="120" Height="23" Background="Orange">
TranslateTransform
Button>
<Button Width="120" Height="23" Background="Lime">
<Button.RenderTransform>
<TranslateTransform X="20" Y="10"/>
Button.RenderTransform>
X=20,Y=20
Button>
(运行效果图)
5)组合变换
根据需求,对元素应用两种以上变换。
示例:一个饱受“折磨”的Button
<Button Width="60" Height="23">
<Button.RenderTransform>
<TransformGroup>
<RotateTransform Angle="45"/>
<ScaleTransform ScaleX="5" ScaleY="1"/>
<SkewTransform AngleX="-30"/>
TransformGroup>
Button.RenderTransform>
OK
Button>
(运行效果图)
布局:面板、自定义面板
将布局后两种方式放在一起说。
布局是一个应用程序在各种设备上可用性的关键体现,但是如果没有好的平台支持,也很难得到正确的布局。
WPF中提供5种内建面板:Canvas、StackPanel、WrapPanel、DockPanel、Grid,以及原始面板TabPanel等。
1.Canvas
最轻量级的面板,很原始,不能用来创建灵活的UI,仅支持用显示的坐标定位元素。允许指定任何角的坐标,而不仅仅是左上角。使用Left、Top、Right、Bottom附加属性在Canvas中来定位元素。与Grid比起来,Grid更耗性能。LayoutTransform属性与RenderTransform不同,一旦被使用,元素总是与被选中的Canvas角保持一定距离。
示例:
XAML:
<Canvas Background="AliceBlue">
<Button Canvas.Left="0" Canvas.Top="0" Background="Orange">Left=0,Top=0Button>
<Button Canvas.Left="15" Canvas.Top="15" Background="AliceBlue">Left=15,Top=15Button>
<Button Canvas.Left="0" Canvas.Bottom="0" Background="AliceBlue">Left=0,Bottom=0Button>
<Button Canvas.Left="15" Canvas.Bottom="15" Background="Orange">Left=15,Bottom=15Button>
<Button Canvas.Right="0" Canvas.Top="0" Background="Green">Right=0,Top=0Button>
<Button Canvas.Right="15" Canvas.Top="15" Background="Aqua">Right=0,Top=15Button>
<Button Canvas.Right="0" Canvas.Bottom="0" Canvas.ZIndex="1" Background="Aqua">
Right=0,Bottom=0Button>
<Button Canvas.Right="15" Canvas.Bottom="15" Background="Green">Right=15,Bottom=15Button>
<Button>OK
<Button.LayoutTransform>
<RotateTransform Angle="30"/>
Button.LayoutTransform>
<Button.RenderTransform>
<RotateTransform Angle="30"/>
Button.RenderTransform>
Button>
Canvas>
2.StackPanel
它是一个受欢迎的面板,因为它方便好用。它会顺序对它的子元素进行排列。它是少数几个没有定义任何附加属性的面板之一。通过设置Orientation为Horizontal或Vertical(默认)来排列子元素。
示例:
XAML:
<StackPanel VerticalAlignment="Top" >
<Button Background="Orange">button1Button>
<Button Background="AliceBlue">button2Button>
<Button Background="Green">button3Button>
<Button Background="Aqua">button4Button>
StackPanel>
<StackPanel VerticalAlignment="Bottom" Height="150" Orientation="Horizontal">
<Button Background="Orange">1Button>
<Button Background="AliceBlue">2Button>
<Button Background="Green">3Button>
<Button Background="Aqua">4Button>
StackPanel>
3.WrapPanel
与StackPanel类似。但是除了会对子元素作栈处理外,当没有足够的控件来放一个栈时,它还会把子元素封装在行或列中。同样没有附加属性来控制元素的位置。
定义了3个控制其行为的属性:
1)Orientation——Horizontal (默认)、Vertical。
2)ItemHeight——所有子元素都一致的高度。每个子元素填充高度的方式取决于VerticalAlignment或Height,任何比ItemHeight高的元素都将被截断。默认没被设置(或Double.NaN)
3)ItemWidth ——所有子元素都一致的宽度。
示例:
XAML:
<WrapPanel ItemHeight="30" ItemWidth="80" VerticalAlignment="Top">
<Button Background="Orange">1Button>
<Button Background="AliceBlue">2Button>
<Button Background="Green">3Button>
<Button Background="Aqua">4Button>
WrapPanel>
<WrapPanel ItemHeight="30" ItemWidth="80" FlowDirection="RightToLeft" VerticalAlignment="Bottom">
<Button Background="Orange">1Button>
<Button Background="AliceBlue">2Button>
<Button Background="Green">3Button>
<Button Background="Aqua">4Button>
WrapPanel>
4.DockPanel
支持让元素简单地停靠在整个面板的某一条边上,然后拉伸元素以填满全部宽度或高度。它也支持让一个元素填充其他已停靠元素没有占用的剩余空间。 附加属性:Dock,类型为System.Windows.Controls.Dock,因此子元素用4个值来控制它们的停靠:
Left、Top、Right、Bottom。注意Dock没有Fill值。作为替代,最后一个子元素将加入一个DockPanel并填满所有剩余的空间,除非DockPanelLastChildFill属性为false。
DockPanel对子元素无数量限制。因此,其功能实际上比StackPanel要强。
示例:
XAML:
<DockPanel>
<Button DockPanel.Dock="Left" Background="Orange">1-LeftButton>
<Button DockPanel.Dock="Right" Background="AliceBlue">2-RightButton>
<Button DockPanel.Dock="Top" Background="Green">3-TopButton>
<Button DockPanel.Dock="Bottom" Background="Aqua">4-BottomButton>
<Button Background="Yellow">5Button>
DockPanel>
5.Grid
最通用的面板。(Visual Studio默认会在项目中使用Grid。)它可以让你在一个多行、多列的表中排列子元素,而不用依靠包装(如WrapPanel),提供了许多特性来有效地控制行和列。很像在HTML中使用Table。(WPF中也包含了一个Table类,为文档的显示专门优化,而Grid是为元素在一个特定的用户界面中显示而优化的。)附加属性:RowSpan、ColumnSpan。
1)改变行和列的尺寸
与FrameworkElement的Height和Width不同,RowDefinition和ColumnDefinition的对应属性值默认不是Auto(或Double.NaN),并且它们是System.Windows.GridLength类型的,而不是double。这样Grid才可以支持3中不同的RowDefinition和ColumnDefinition尺寸:绝对尺寸,自动尺寸:Auto,比例尺寸:2*、*(占据所有剩余空间)等。
2)与GridSplitter交互改变尺寸
可以使用鼠标、键盘或指示笔来改变尺寸。这是由来自于同一个命名空间下的GridSplitter类完成的。也可以添加多个GridSplitter到Grid中,并设置它们的Grid.Now、Grid.Column、Grid.RowSpan和Grid.ColumnSpan附加属性值,就像Grid其他子元素一样。
3)共享行和列的尺寸
RowDefinition和ColumnDefinition有一个叫作SharedSizeGroup的属性,允许多行或多列与其他行或列保持一样的长度,即使其中的行或列在运行时(例如,使用GridSplitter)改变也是如此。SharedSizeGroup可以被设置为一个大小写敏感的字符串值,表示某个组的名称,其他拥有相同组名的行或列将保持同步。
4)Grid与其他面板的比较
在大多数布局方案中Grid通常是最好的选择,因为除了WrapPanel包装功能以外,它其实可以用前面提到的面板做任何事。Grid也可以实现一些原本需要多个面板实现的布局。
5)Grid模拟其他面板
a)模拟Canvas Grid只有一行一列,设置所有子元素的HorizontalAlignment和VerticalAlignment为除了Stretch以外的值,子元素将被添加到那个单元格中。
b)模拟StackPanel 一行连续多列,或一列连续多行。
c)模拟DockPanel 可以使用RowSpan和ColumnSpan布局顶部的元素,让它们停靠和拉伸到Grid边缘上。
示例:
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
<RowDefinition Height="50"/>
Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Background="Orange">
Row=0,Column=0Label>
<Label Grid.Row="0" Grid.Column="1" Background="Green">
Row=0,Column=1Label>
<Label Grid.Row="1" Grid.Column="1" Background="AliceBlue">
Row=1,Column=1Label>
<Label Grid.Row="2" Grid.Column="0" Background="Green">
Row=2,Column=0Label>
<Label Grid.Row="2" Grid.Column="1" Background="PaleGoldenrod">
Row=2,Column=1Label>
<GridSplitter Grid.Column="0" Grid.Row="2" Width="10" Background="White"/>
Grid>
6.原始面板
1) TabPanel
2)ToolBarOverflowPanel 简化的WrapPanel,仅支持从左到右、从上至下排列。
3)ToolBarTray 仅支持ToolBar的子元素。
4)UniformGrid Grid的简化形式,所有行和列的大小设置都是*,且不能改变。
布局:自定义面板
实现一个自定义面板是一个“高级主题”,因为很少这么做。创建自定义面板没有特殊的机制,所以你可以使用内建面板相同上的方式来创建自定义面板。
数据绑定
需要弄清几个问题:
1.数据绑定概念
2.数据绑定方式
3.数据更新方式
1.什么是数据绑定?将两个相同类型或可以互相转化的类型的数据粘在一起。最常见的情况,就是将一个被动变化的数据绑定到主动数据上,从而达到被动数据随主动数据变化的目的。
数据绑定的核心即在程序中设定一个数据和另一个数据的值保持相同。
看完概念描述,可能会觉得“绑定”有点不大合适,似乎是固定不变了;说“关联”比较形象,有一种联动的概念在里面。是不是Binding的音译呢?
如果不太理解,可以通过以下示例去充分体会。
示例:在窗口底部显示选中项
使用TreeView、TextBlock控件实现。
要实现以上功能,首先明确绑定是通过System.Window.Data.Binding类实例表示的。
2.绑定的实现有两种方式:
1)后台代码绑定
实现步骤:
Binding binding = new Binding(); //1.创建Binding实例
binding.Source = treeView; //2.设置源对象,TreeView控件Name
binding.Path = new PropertyPath("SelectedItem.Header");//3.设置源对象的属性
textBlock.SetBinding(TextBlock.TextProperty, binding);//4.添加到目标属性,TextBlock的Name
注意:
a.目标属性是跟随源属性值变化
b.源属性可以是一般的.net属性,如TreeView的选中项的Header;
c.目标属性则必须是依赖属性,如TextBlock的TextProperty,依赖属性以Property后缀。
2)XAML绑定
实现方式:
<TreeView Name="treeView">
<TreeViewItem Header="item1">
<TreeViewItem Header="it1"/>
TreeViewItem>
<TreeViewItem Header="item2">
TreeViewItem>
TreeView>
<TextBlock Name="textBlock" VerticalAlignment="Bottom" FontSize="20" Text="{Binding ElementName=treeView,Path=SelectedItem.Header}">TextBlock>
注意:
a.源元素名称——ElementName
b.源属性——Path
c.Binding本身是一个标记扩展类,尽管名字中没有带Extension后缀,属非标准标记扩展。
3.数据更新的机制
这样说好像不易理解,说白了就是谁更新谁?什么时候更新?
1)谁更新谁?
更新方式有以下几种(之后会有一个简单的demo去帮助理解这几种更新方式):
a.OneWay——数据源的任何更新都会导致目标数据的更新。而目标数据的更新不会导致数据源更新,却会导致数据源被清除。
b.TwoWay——无论是数据源还是目标数据,对它的更新都会导致对方的更新。
c.OneWayToSource——目标数据的任何更新都会导致数据源的更新。与OneWay相反。
d.OneTime——目标数据只有在绑定初始化的时候才会被更新。
2)什么时候更新?
WPF提供了3种刷新方式,对这3种刷新方式是通过UpdateSourceTrigger属性完成的。它是一个枚举类型,而不是一个Trigger类型。
a. Default 该属性的默认值,对数据的更新会根据参与绑定的属性进行相应的更改。对大多数参与绑定的属性来说,对绑定的UpdateSourceTrigger属性设置为该值与设置为PropertyChanged相同,而对于绑定的目标属性为Text的时候,其行为与设置为LostFocus相同。
b. PropertyChanged 只要数据源中有任意的更改,数据绑定机制将自动刷新目标数据的值。
c. LostFocus 当绑定的目标失去输入焦点时,目标数据的值将被刷新。
d. Explicit 只有在调用BindingExpression的UpdateSource函数的情况下,目标数据的值才会被刷新。
4.示例(关于更新方式的demo):
在TextBox1中填写abc,那么在TextBox2中也显示abc等效果。
XAML:
<StackPanel>
<Label Content="TextBox1"/>
<TextBox x:Name="textBox1"/>
<Label Content="TextBox2"/>
<TextBox x:Name="textBox2"
Text="{Binding ElementName=textBox1,Path=Text,Mode=Default }"/>
StackPanel>
更新方式:
a.Default时,textBox1(以下简称1)值变,则textBox2(简称2)值变,2变1变(但须鼠标定位到1);
b.OneTime时,只有第一次加载时,2的值与1值同;
c.OneWay时,1变2变,2变1不变;
d.OneWayToResource时,1变2不变,2变1变,与OneWay相反;
e.TwoWay时,1变2变,2变1变。
通常的数据绑定,如在asp.net中绑定DropDownList、DataGridView等都是使用其DataSource属性在WPF中进行数据源绑定使用ItemSource属性,有些区别。
样式、模板、皮肤、主题
这部分虽然觉得似乎是UI设计者的工作范畴,但也应该知道如何去使用。
关于这部分的概念性的内容在下边列出,相应的demo,可以在http://www.itkj0315.com/KindEditor/attached/file/20120104/20120104172106_1250.rar进行下载。
WPF提供的用于改变风格的4种主要组件:
样式 一种简单的机制,可以把属性值和用户界面元素分离开来(类似于重叠样式表CSS和HTML的关系),也是应用本章其他机制的基础。
模板 当人们谈论WPF的改变风格功能(restyling)时,时常提到。
皮肤 应用程序级的样式和模板集合,通常能够被动态地替换。
主题 宿主操作系统的视觉特性,可由最终用户自定义。
1.样式
由System.Window.Style类表示,它是一种非常简单的实体。它的主要功能是对属性值分组,否则这些属性值就将被单独设置。样式存在的目的是在多个元素中共享改组的值。
提示:一个Style可以从另一个Style继承。通过使用BasedOn属性实现。
1.共享Style
1)在不同种类的元素间共享
为了在Style中共享复杂的属性值,Style自己拥有一个Resource属性。可以利用这个集合时Style变得更独立,而不是从其他地方获得资源。
2)限制Style的使用
通过TargetType限制应用此样式的目标类型元素。
3)创建隐式Style
忽略Key属性,那么该Style被隐式的应用到所有目标类型元素。通常称作类型化样式。其有效范围有Style的资源位置决定。
2.触发器
触发器有一个Setter集合,与Style是一样的。通常一个样式时无条件的应用它的值,但一个触发器则会根据一个或多个条件执行它的任务。
1)属性触发器 当依赖属性值改变时调用
2)数据触发器 当普通.NET属性值改变时调用
3)事件触发器 当路由事件被触发时调用
2.模板
1.控件模板
ControlTemplate类的重要部分是它的VisualTree内容属性,它包含了定义你想要的外观的元素树。
2.与触发器交互
因为有了样式,Template在Triggers集合中可以包含各种类型的触发器。
3.限制目标类型
与Style一样,使用TargetType属性限制模板可以被应用到的元素。
将模板与样式混合起来!
控件模板直接被应用到元素很方便。但在一个Style内部设置Control的Template属性,然后把该样式应用到指定元素上更常见。优势:带给你默认模板的效果;允许提供默认但是可重载的属性值,用于控制模板的外观。
3.皮肤
换肤就是随意改变应用程序的外观(或皮肤),通常由第三方完成。WPF并没有独特的叫作皮肤的概念,也没有一个正式的换肤概念,因为WPF不需要。可以用WPF写一个支持动态换肤的应用程序或组件,这可以通过WFP的动态资源机制加上Style和模板来实现。
4.主题
皮肤是跟着应用程序走的,但主题通常涉及操作系统的视觉特性,它会反映在所有程序的界面的元素上。例如,XP中改变默认主题的色彩方案会影响标准控件的颜色和发光效果。
通常两种方式实现创建应用到当前主题的样式和模板:1.使用系统颜色、字体和参数,2.每个主题的样式和模板。
富媒体(2D、3D图像)
首先明确什么是富媒体?富媒体(Rich Media)包括多媒体(二维和三维动画、声音及影像)。富媒体本身不是信息,但是它可以加强信息。例如通常我们可以在门户网站中看到诸多广告,有动画的(如Falsh),有声音,有视频的等等,这些都是富媒体应用。目的就是更直观准确的传递商品等的有效信息,以提高广告主的收益等等。那么,在WPF中,我所关注的富媒体,是丰富用户体验,更好的传达软件本身信息,完善人机交流。还是那句话,加强用户体验感。这也是这些年软件设计开发者一直努力达成的目标。
峰回路转,进入正题。在这部分中,简单介绍2D、3D图形以及音频、视频,重点是动画实现。
1.2D图形
2D图形,就是二维平面图形。其中涉及3个重要的数据类型:Drawing、Visual和Shape。
Drawing:对与填充相关联的路径和形状的简单描述以及轮廓Brush。
Visual:把Drawing滑到屏幕的一种方式,但它也提供了完全摆脱Drawing对象的底层轻量级实现。
Shape:预制的Visual,它是在屏幕上画自定义工艺图最简单(也是最轻量级)的方法。
1)Drawing
包括5种Drawing类的具体子类:
GeometryDrawing:包括Geometry类,用来填充的Brush类,以及用来画轮廓的Pen类。
ImageDrawing:包括ImageSource类,以及用来定义边界的Rect类。
VideoDrawing:包括了MediaPlayer类,以及定义边界的Rect类。
VideoDrawing:包括了MediaPlayer类,以及定义边界的Rect类。
GlyphRunDrawing:包括GlyphRun类,低级别的文本类,以及来绘制前景色的Brush类。
DrawingGroup:一组Drawing对象的集合类,有一组属性可以用哦过来批量修改包含的所有Drawing对象的内容(例如不透明、变换等)。
示例:使用DrawingImage类将GeometryDrawing画到屏幕上。因为Drawing本身不是UIElement,本身没有绘画的能力,因此,需要添加到相应的宿主对象中,比如下例中的Image。
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="Orange">
<GeometryDrawing.Pen>
<Pen Brush="Black" Thickness="5"/>
GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<EllipseGeometry RadiusX="100" RadiusY="50"/>
GeometryDrawing.Geometry>
GeometryDrawing>
DrawingImage.Drawing>
DrawingImage>
Image.Source>
Image>
显示了包含GeometryDrawing的Image的绘制效果。
2)Visual
Visual是UIElement类的抽象基类(UIElement类是FrameworkElement的基类),包含了画任何东西到屏幕上的下层基本构造。
a.用内容填充DrawingVisual
b.在屏幕上显示Visual
c.可视命中测试
首先看一个命中测试的demo:
术语中“命中测试”,指的是判断一个点(或是一组点)是否与一个给定的对象相交。在鼠标相关的事件上下文经常会做这样的事,这时候上例种的点就是鼠标指针的位置,给定的对象就是圆形。
关于上例的相关代码可以在文章结束的下载demo中的VisualTest中查看。
3)Shape
就像GeometryDrawing一样是基本的二位图画,结合了Geometry、Pen和Brush。与GeometryDrawing不同的是,Shape派生自FrameworkElement,所以可以直接放在一个用户界面里,也就是说它不需要宿主。
WPF派生自System.Windows.Shape.Shape抽象类中的6个类:
§ Rectangle
§ Ellipse
§ Line
§ Polyline
§ Polygon
§ Path
下图中是使用Rectangle类实现的两个矩形。
2.3D图形
三维立体图形。由于3D图形已经成为WPF平台的组成部分了,所以2D图像和其他许多概念在这里是被重用和共享的。3D包含在Viewport3D中的场景可以与程序其他UIElement实现无缝融合,同时它也可以被放入模板或ItemsControl中。
通常画3D图形可以使用设计工具Blend或是ZAM3D,然后导出XAML代码粘贴在相应位置就可以。对于接触过3D图形的人来说,Camera、Material和Lights不陌生。没错,它们就是构成3D图形的必要元素。相机用来模拟观察者效果;材质不同,图形表面显出的效果不同;模拟光源显出图形的高光暗调。
示例:
同样demo涉及的代码可以在http://www.itkj0315.com/KindEditor/attached/file/20120105/20120105111906_4375.rar下载。
富媒体(动画、音频、视频)
接上,这里的动画是图形的动画。
3.动画
动画效果的实现,可以有以下两种:
1)程序代码实现
用代码实现又有两种方式:
a.手工实现:可以使用定时器,但是不推荐。因为定时器无法根据显示器的垂直刷新率进行同步,也不能与WPF的渲染引擎同步。
b.使用动画类
动画类位于System.Windows.Media.Animation命名空间下,这些动画有两个重要方面:
i.只能改变一个依赖属性的值
ii.使动画变得“时间分辨率无关”
2)XAML实现
先看一个demo运行效果:
实现代码:
<Grid>
<Grid.Background>
<LinearGradientBrush>
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="Black" Offset="0.5"/>
<GradientStop Color="Blue" Offset="1"/>
LinearGradientBrush>
Grid.Background>
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetProperty="Background.GradientStops[1].Color"From="Black" To="White" Duration="0:0:3" AutoReverse="True" RepeatBehavior="Forever"/>
<DoubleAnimation Storyboard.TargetProperty="Background.GradientStops[1].Offset"From="0" To="1" Duration="0:0:3" AutoReverse="True" RepeatBehavior="Forever"/>
Storyboard>
BeginStoryboard>
EventTrigger>
Grid.Triggers>
Grid>
对上例中进行分析:
LinearGradientBrush画出渐变效果;
使用事件触发器Trigger,在Grid的Loaded事件中,使用ColorAnimation、DoubleAnimation类改变Grid的Background中的属性值,达到以上运行效果。
ColorAnimation、DoubleAnimation类中涉及的属性:
w 附加属性Storyboard.TargetProperty,目标属性。
w From、To 起始、结束值,变颜色就是颜色值,变数值就是数字。
w Duration 动画持续的时间,如0:0:3就是3秒。
w AutoReverse 是否支持往返,为true时,动画往返一次结束,如上例中变色值从黑到白再到黑,是一次反复。
w RepeatBehavior 重复特性,为Forever时,动画无休止的循环执行。
使用动画类,可以做出类似电影片尾效果,如下图,代码见FilmAnimation:
其他几种动画效果,你可以查看demo。
注意:动画耗性能,酌情使用。
4.音频
通过SoundPlayer、MediaPlayer、SoundPlayerAction、MediaElement和MediaTimeline可以实现。效果可查看demo。
5.视频
WPF的视频支持也是基于前面一节描述的MediaPlayer类,以及它的伙伴类,如MediaPlayer和MediaTimeline。因此,Windows Media Player支持播放的所有文件格式可以很容易地在WPF应用程序中使用(如.wmv、.avi、.mpg等)。
注意:WPF的音频和视频支持必须安装Windows Media Player 10或更高版本!(未安装将报出一个异常)在Windows Vista之前,只有32位的Windows Media Player!(确保应用程序以32位运行)。
如下简单视频播放器效果:
*文章涉及的demo,可以从http://www.itkj0315.com/KindEditor/attached/file/20120105/20120105112611_6562.rar下载。
完结(附上一个拼图游戏)
到这篇文章,关于WPF的基本应用完结,文章观点难免有出入,欢迎指正,共同进步。
WPF作为新一代的C/S应用程序开发的老大,有着其他技术不可比拟之处,更深入的研究等待你去不断探索。近两年,你会发现有些公司的招聘要求中写着熟悉WPF的优先,所以作为求职中的加分点,有必要去了解。
下边附上一个拼图游戏,感兴趣的话可以了解。主要使用的装饰器,这个在之前的文章中并未提到。运行此程序至少需要框架.NET Framework 4 Client Profile,如果你已安装.NET Framework 4.0 Full版,则可直接运行。效果图如下:
点击这里下载拼图游戏。
使用WPF技术开发的设备管理系统截图:
初学乍练系列之WPF完结。
From: IT空间-Lee~的空间(http://www.itkj0315.com/kj.aspx?wz_id=803)