# WPF快速入门系列(1)——WPF布局概览
## 一、引言
关于WPF早在一年前就已经看过《深入浅出WPF》这本书,当时看完之后由于没有做笔记,以至于我现在又重新捡起来并记录下学习的过程,本系列将是一个WPF快速入门系列,主要介绍WPF中主要的几个不同的特性,如依赖属性、命令、路由事件等。
在正式介绍之前,我还想分享下为什么我又要重新捡起来WPF呢?之前没有记录下来的原来主要是打算走互联网方向的,后面发现互联网方向经常加班,又累,有时候忙的连自己写了什么都不知道的,所以后面机缘巧合地进了一家外企,在外企不像互联网行业那样,比较清楚,有更多的时间去理清楚自己所学习到的知识,其中同时也发现了WPF的重要性和应用场景,在一些美资企业和印度的公司,客户端都非常喜欢用WPF来做演示的客户端,所以,自然走上外企这条路,所以就打算好好研究下WPF了,所以也就有了这个系列。
## 二、WPF的自我介绍
Windows Presentation Foudation,WPF是下一代显示系统,用来生成能带给用户震撼视觉体验的Windows客户端应用程序。WPF的核心是一个与分辨率无关并且基于向量的程序引擎,目的在于利用现代图形硬件的优势。WPF在.NET Framework 3.0中被微软引入到.NET Framework类库中,并且在.NET 3.5、4.0 和4.5都有所更新。WPF可以理解为是实现下一代Windows 桌面应用程序的技术,在之前我们通常会使用MFC或Winform来实现Windows桌面程序。
WPF除了引入了新的API之前,还引入了一些新的概念,这些新的概念会在本系列中一一介绍。众所周知,在实现桌面应用程序之前,第一步必然是对窗体进行布局,WPF为了更好地实现布局,提供了很多布局控件,下面就让我们一起去看看WPF布局组件。
## 三、WPF布局详解
WPF的布局控件都继承于System.Windows.Controls.Panel这个类,本文主要介绍在Panel基类下的几个常用的布局控件。下图是布局控件的继承关系:
![](https://box.kancloud.cn/2016-01-23_56a2eb40084b4.png)
## 3.1 WPF布局过程
WPF布局包括两个阶段:**一个测量(measure)阶段和一个排列(arrange)阶段**。在测量阶段,容器遍历所有子元素,并询问子元素它们所期望的大小。在排列阶段,容器在合适的位置放置子元素。WPF布局可以理解为一个递归过程,它会递归对布局控件内的每个子元素进行大小调整,定位和绘制,最后进行呈现,直到递归所有子元素为止,这样也就完成了整个布局过程。
布局系统为每个子元素完成了两个处理过程:测量处理和排列处理。每个Panel都提供了自己的**[MeasureOverride](http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelement.measureoverride(v=vs.110).aspx)**和**[ArrangeOverride](http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelement.arrangeoverride(v=vs.110).aspx)**方法,以实现自己特定的布局行为。所以,你如果想自定义布局控件,也可以重新这两个方法来达到,关于自定义布局控件会在后面介绍到。
## 3.2 Canvas 布局控件
Canvas面板是最轻量级的布局容器,它不会自动调整内部元素的排列和大小,不指定元素位置,元素将默认显示在画布的左上方。Canvas主要用来画图。Canvas默认不会自动裁剪超过自身范围的内容,即溢出的内容会显示在Canvas外面,这是因为Canvas的ClipToBounds属性默认值是false,我们可以显式地设置为true来裁剪多出的内容。下面XAML代码简单演示了Canvas面板的使用。
上面XAML实现的效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb401d283.png)
其中,矩形的右边区域以溢出Canvas面板区域,如向右拉动边框,此时Canvas会拉伸以填满可用空间,此时就可以看到矩形溢出的部分。但Canvas面板内的控件不会改变其尺寸和位置。对应的C#代码实现如下所示:
```
1 public partial class CanvasDemo : Window
2 {
3 public CanvasDemo()
4 {
5 InitializeComponent();
6
7 Canvas canv = new Canvas();
8 canv.Margin = new Thickness(10, 10, 10, 10);
9 canv.Background = new SolidColorBrush(Colors.White);
10
11 // 把canv添加为窗体的子控件
12 this.Content = canv;
13
14 // Rectangle
15 Rectangle rect = new Rectangle();
16 rect.Fill = new SolidColorBrush(Colors.Black);
17 rect.Stroke = new SolidColorBrush(Colors.Red);
18 rect.Width = 200;
19 rect.Height = 200;
20 rect.SetValue(Canvas.LeftProperty, (double)300);
21 rect.SetValue(Canvas.TopProperty, (double)180);
22 canv.Children.Add(rect);
23
24 // Ellipse
25 Ellipse el = new Ellipse();
26 el.Fill = new SolidColorBrush(Colors.Azure);
27 el.Stroke = new SolidColorBrush(Colors.Green);
28 el.Width = 180;
29 el.Height = 180;
30 el.SetValue(Canvas.LeftProperty, (double)160);
31 // 必须转换为double,否则执行会出现异常
32 // 详细介绍见:http://msdn.microsoft.com/zh-cn/library/system.windows.controls.canvas.top(v=vs.110).aspx
33 el.SetValue(Canvas.TopProperty, (double)150);
34 el.SetValue(Panel.ZIndexProperty, -1);
35 canv.Children.Add(el);
36
37 // Print Zindex Value
38 int zRectIndex = (int)rect.GetValue(Panel.ZIndexProperty);
39 int zelIndex = (int)el.GetValue(Panel.ZIndexProperty);
40 Debug.WriteLine("Rect ZIndex is: {0}", zRectIndex);
41 Debug.WriteLine("Ellipse ZIndex is: {0}", zelIndex);
42 }
43 }
```
从上面可以看出,即使C#代码可以实现完全一样的效果,但是需要书写更多的代码,所以,在平时开发中,对于控件的布局,一般采用XAML的方式,C#代码一般用于在运行时加载某个控件到界面中的实现。
## 3.3 StackPanel 布局控件
StackPanel就是将子元素按照堆栈的形式一一排列,可以通过设置StackPanel的Orientation属性设置两种排列方式:横排(Horizontal,该值为默认值)和竖排(Vertical)。纵向的StackPanel每个元素默认宽度与面板一样宽,反之横向是高度和面板一样高。如果包含的元素超过了面板控件,它会被截断多出的内容。可以通过Orientation属性来设置StackPanel是横排(设置其值为Vertical)还是竖排(设置其值为Horizontal)。下面XAML代码演示了StackPanel的使用:
```
1 <Window x:Class="WPFLayoutDemo.StackPanelDemo"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="StackPanel" Height="300" Width="200">
5 <StackPanel Margin="10,10,10,10" Background="Azure">
6 <Label>A Button Stack</Label>
7 <Button Content="Button 1"></Button>
8 <Button>Button 2</Button>
9 <Button>Button 3</Button>
10 <Button Content="Button 4"></Button>
11 </StackPanel>
12 </Window>
```
对应的C#实现代码如下所示:
```
1 public partial class StackPanelDemo : Window
2 {
3 public StackPanelDemo()
4 {
5 InitializeComponent();
6 StackPanel sp = new StackPanel();
7 sp.Margin = new Thickness(10, 10, 10, 10);
8 sp.Background = new SolidColorBrush(Colors.Azure);
9 sp.Orientation = Orientation.Vertical;
10 // 把sp添加为窗体的子控件
11 this.Content = sp;
12
13 // Label
14 Label lb = new Label();
15 lb.Content = "A Button Stack";
16 sp.Children.Add(lb);
17
18 // Button 1
19 Button btn1 = new Button();
20 btn1.Content = "Button 1";
21 sp.Children.Add(btn1);
22
23 // Button 2
24 Button btn2 = new Button();
25 btn2.Content = "Button 2";
26 sp.Children.Add(btn2);
27
28 // Button 3
29 Button btn3 = new Button();
30 btn3.Content = "Button 3";
31 sp.Children.Add(btn3);
32
33 // Button 4
34 Button btn4 = new Button();
35 btn4.Content = "Button 4";
36 sp.Children.Add(btn4);
37 }
38 }
```
上面代码的实现效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb402e675.png)
如果将StackPanel的Orientation属性设置为“Horizontal”的话,此时的效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb403c186.png)
尽管布局由容器决定,但子元素仍然有一定的决定权,布局面板支持一些布局属性,以便与子元素结合使用,在下图中列出了这些布局属性:
![](https://box.kancloud.cn/2016-01-23_56a2eb404bac7.png)
## 3.4 WrapPanel 布局控件
WrapPanel面板在可能的空间中,一次以一行或一列的方式布置控件。默认情况下,WrapPanel.Orientation属性设置为Horizontal,控件从左向右进行排列,然后再在下一行中排列,但你可将WrapPanel.Orientation设置为Vertical,从而在多个列中放置元素。与StackPanel面板不同,WrapPanel面板实际上用来控制用户界面中一小部分的布局细节,并非用于控制整个窗口布局。
下面示例中定义了一系列具有不同对齐方式的按钮,并将这些按钮放在一个WrapPanel面板中。
```
1 <Window x:Class="WPFLayoutDemo.WrapPanelDemo"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="WrapPanelDemo" Height="300" Width="500">
5 <WrapPanel Margin="10" Background="Azure">
6 <Button VerticalAlignment="Top" Margin="5">Top Button</Button>
7 <Button MinHeight="50"> Tall Button 2</Button>
8 <Button VerticalAlignment="Bottom">Bottom Button</Button>
9 <Button>Stretch Button</Button>
10 <Button VerticalAlignment="Center">Center Button</Button>
11 <Button>Next Button</Button>
12 </WrapPanel>
13 </Window>
```
下图显示了如何对这些按钮进行换行以适应WrapPanel面板的当前尺寸,WrapPanel面板的当前尺寸由包含它的窗口尺寸决定的。在上面的例子中,WrapPanel面板水平地创建一系列假象的行,每一行的搞定都被设置为所包含元素中最高元素的高度。其他空间可能被拉伸以适应该高度,或根据VerticalAlignment属性设置进行对齐。
![](https://box.kancloud.cn/2016-01-23_56a2eb4060bc6.png)
当缩小窗口大小时,对应的WrapPanel也会改变,从而改变WrapPanel面板中控件的排列,具体效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb4071486.png)
## 3.5 DockPanel 布局控件
DockPanel面板定义一个区域,在此区域中,你可以使子元素通过锚点的形式进行排列。DockPanel类似于WinForm中Dock属性的功能。对于在DockPanel中的元素的停靠可以通过Panel.Dock的附加属性来设置,如果设置LastChildFill属性为true,则最后一个元素将填充剩余的所有空间。
下面XAML代码演示了DockPanel控件的使用:
```
1 <Window x:Class="WPFLayoutDemo.DockPanelDemo"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="DockPanelDemo" Height="300" Width="300">
5 <DockPanel Margin="10" Background="Azure" LastChildFill="True">
6 <Button DockPanel.Dock="Top" Background="Red">Top Button</Button>
7 <Button DockPanel.Dock="Left" Background="Gray">Left Button</Button>
8 <Button DockPanel.Dock="Right" Background="Green">Right Button</Button>
9 <Button DockPanel.Dock="Bottom" Background="White">Bottom Button</Button>
10 <Button>Remaining Button</Button>
11 </DockPanel>
12 </Window>
```
运行的效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb40816d2.png)
## 3.6 Grid 布局控件
Grid比起其他Panel,功能是最多最为复杂的布局控件。它由<Grid.ColumnDefinitions>列元素集合和<Grid.RowDefinitions>行元素集合两种元素组成。而放在Grid面板中的元素必须显式采用附加属性定义其所在行和列,否则元素均默认放置在第0行第0列。下面XAML演示了Grid面板的使用:
```
1 <Window x:Class="WPFLayoutDemo.GridDemo"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="GridDemo" Height="300" Width="480">
5 <Grid Width="Auto" Height="Auto">
6 <Grid.RowDefinitions>
7 <RowDefinition Height="*"/>
8 <RowDefinition Height="Auto"/>
9 </Grid.RowDefinitions>
10 <Grid.ColumnDefinitions>
11 <ColumnDefinition Width="120"/>
12 <ColumnDefinition Width="150"/>
13 <ColumnDefinition Width="*"/>
14 <ColumnDefinition Width="2*"/>
15 </Grid.ColumnDefinitions>
16 <Rectangle Grid.Row="0" Grid.Column="0" Fill="Green" Margin="10,10,10,20"/>
17 <Rectangle Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" Fill="Blue" Margin="10,10,10,20"/>
18 <Rectangle Grid.Row="0" Grid.Column="4" Fill="Orange"/>
19 <Button Grid.Row="1" Grid.Column="0">Button 2</Button>
20 <Rectangle Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3" Fill="Red"/>
21 </Grid>
22 </Window>
```
定义Grid的列宽和行高可采用固定、自动和按比例三种方式定义。
第一种:固定长度——宽度不够时,元素会被裁剪,单位是pixel;
第二种:自动长度——自动匹配行中最宽元素的高度。
第三种:比例长度——"*"表示占用剩余的全部宽度或高度,两行都是*,则将剩余高度平分。像上面的一个2*,一个*,表示前者2/3宽度。
其运行效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb40909a6.png)
## 3.7 UniformGrid 布局控件
UniformGrid是Grid简化版本,不像Grid面板,UniformGrid不需要预先定义行集合和列集合,反而,通过简单设置Rows和Columns属性来设置尺寸。每个单元格始终具有相同的大小。UniformGrid每个单元格只能容纳一个元素,将自动按照在其内部的元素个数,自动创建行和列,并通过保存相同的行列数。
下面XAML演示了UniformGrid控件的使用:
```
1 <Window x:Class="WPFLayoutDemo.UniformGridDemo"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="UniformGridDemo" Height="300" Width="300">
5 <UniformGrid>
6 <Ellipse Margin="10" Fill="Gray"/>
7 <Ellipse Margin="10" Fill="Gray"/>
8 <Ellipse Margin="10" Fill="Green"/>
9 <Ellipse Margin="10" Fill="Green"/>
10 <Ellipse Margin="10" Fill="Red"/>
11 </UniformGrid>
12 </Window>
```
在上面,并没有显示指定UniformGrid的行和列数,此时UniformGrid将自动按照元素的个数,自动创建行和列。运行效果如下图所示。最好是显式指定Rows和Columns属性,这样才能确保布局是按照你的思路去进行的。
![](https://box.kancloud.cn/2016-01-23_56a2eb409ee0a.png)
## 3.8 ScrollViewer 控件
通常用户界面中的内容比计算机屏幕的显示区域大的时候,可以利用[ScrollViewer](http://msdn.microsoft.com/zh-cn/library/system.windows.controls.scrollviewer(v=vs.110).aspx)控件可以方便地使应用程序中的内容具备滚动功能。具体的使用示例如下所示:
```
1 <Window x:Class="WPFLayoutDemo.ScrollViewerDemo"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 Title="ScrollViewerDemo" Height="300" Width="300">
5 <Grid>
6 <ScrollViewer **HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto"**>
7 <Rectangle Width="500" Height="400" Fill="Green"/>
8 </ScrollViewer>
9 </Grid>
10 </Window>
```
运行效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb40b2d56.png)
## 四、布局综合运用
前面例子都是单独介绍每个布局控件的,然而在实际开发中,程序的界面布局都是由多个布局控件一起来完成的,这里演示一个综合实验的小例子。要实现的效果图如下所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb40c4761.png)
具体的XAML代码实现如下所示:
```
1 <Window x:Class="WPFLayoutDemo.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 WindowStartupLocation="CenterScreen"
5 Title="布局综合运用实例" Height="400" Width="480">
6 <DockPanel Width="Auto" Height="Auto" LastChildFill="True">
7 <!--顶部菜单区域-->
8 <Menu Width="Auto" Height="20" Background="LightGray" DockPanel.Dock="Top">
9 <!--File菜单项-->
10 <MenuItem Header="文件">
11 <MenuItem Header="保存"/>
12 <Separator/>
13 <MenuItem Header="退出"/>
14 </MenuItem>
15 <!--About 菜单项-->
16 <MenuItem Header="帮助">
17 <MenuItem Header="关于本产品"/>
18 </MenuItem>
19 </Menu>
20
21 <!--状态栏-->
22 <StackPanel Width="Auto" Height="25" Background="LightGray" Orientation="Horizontal" DockPanel.Dock="Bottom">
23 <Label Width="Auto" Height="Auto" Content="状态栏" FontFamily="Arial" FontSize="12"/>
24 </StackPanel>
25 <!--Left-->
26 <StackPanel Width="130" Height="Auto" Background="Gray" DockPanel.Dock="Left">
27 <Button Margin="10" Width="Auto" Height="30" Content="导航栏"/>
28 <Button Margin="10" Width="Auto" Height="30" Content="导航栏"/>
29 <Button Margin="10" Width="Auto" Height="30" Content="导航栏"/>
30 </StackPanel>
31
32 <!--Right-->
33 <Grid Width="Auto" Height="Auto" Background="White">
34
35 <Grid.ColumnDefinitions>
36 <ColumnDefinition Width="*"/>
37 <ColumnDefinition Width="*"/>
38 </Grid.ColumnDefinitions>
39
40 <Grid.RowDefinitions>
41 <RowDefinition Height="*"/>
42 <RowDefinition Height="*"/>
43 </Grid.RowDefinitions>
44
45 <Rectangle Fill="Gray" Margin="10,10,10,10" Grid.Row="0" Grid.Column="0"/>
46 <Rectangle Fill="Gray" Margin="10,10,10,10" Grid.Row="0" Grid.Column="1"/>
47 <Rectangle Fill="Gray" Margin="10,10,10,10" Grid.Row="1" Grid.Column="0"/>
48 <Rectangle Fill="Gray" Margin="10,10,10,10" Grid.Row="1" Grid.Column="1"/>
49 </Grid>
50 </DockPanel>
51
52 </Window>
```
## 五、自定义布局控件
在实际开发中,自然少不了自定义控件的开发,下面介绍下如何自定义布局控件。在前面介绍过布局系统的工作原理是先测量后排列,测量即是确定面板需要多大空间,排列则是定义面板内子元素的排列规则。所以,要实现自定义布局控件,需要继承于Panel类并重写MeasureOverride和ArrangeOverride方法即可,下面实现了一个简单的自定义布局控件:
```
1 namespace CustomLayoutControl
2 {
3 public class CustomStackPanel: Panel
4 {
5 public CustomStackPanel()
6 : base()
7 {
8 }
9
10 // 重写默认的Measure方法
11 // avaiableSize是自定义布局控件的可用大小
12 protected override Size MeasureOverride(Size availableSize)
13 {
14 Size panelDesiredSize = new Size();
15 foreach (UIElement child in this.InternalChildren)
16 {
17 child.Measure(availableSize);
18
19 // 子元素的期望大小
20 panelDesiredSize.Width += child.DesiredSize.Width;
21 panelDesiredSize.Height += child.DesiredSize.Height;
22 }
23
24 return panelDesiredSize;
25 }
26
27 // 重写默认的Arrange方法
28 protected override Size ArrangeOverride(Size finalSize)
29 {
30 double x = 10;
31 double y = 10;
32 foreach (UIElement child in this.InternalChildren)
33 {
34 // 排列子元素的位置
35 child.Arrange(new Rect(new Point(x, y), new Size(finalSize.Width - 10, child.DesiredSize.Height)));
36 y += child.RenderSize.Height + 5;
37 }
38
39 return finalSize;
40 }
41 }
42 }
```
控件的最终大小和位置是由该控件和父控件共同完成的,父控件会先给子控件提供可用大小(MeasureOverride中availableSize参数),子控件再反馈给父控件一个自己的期望值(DesiredSize),父控件最后根据自己所拥有的空间大小与子控件期望的值分配一定的空间给子控件并返回自己的大小。这个过程是通过MeasureOverride和ArrangeOverride这两个方法共同完成的,这里需要注意:父控件的availableSize是减去Margin、Padding等的值。
接下来,创建一个测试上面自定义布局控件的WPF项目,然后添加自定义布局控件的程序集,然后在WPF项目中MainWindows添加如下代码:
```
1 <Window x:Class="TestCustomerPanel.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 ** xmlns:custom="clr-namespace:CustomLayoutControl;assembly=CustomLayoutControl"**
5 Title="测试自定义布局控件" Height="350" Width="525">
6 <custom:CustomStackPanel Background="Red">
7 <Button Content="Button 1"></Button>
8 <Button Content="Button 2"></Button>
9 <Button Content="Button 3"></Button>
10 </custom:CustomStackPanel>
11 </Window>
```
运行成功后的效果如下图所示:
![](https://box.kancloud.cn/2016-01-23_56a2eb40d9ac1.png)
## 六、小结
到这里,WPF布局的内容就介绍结束了,这里最后只是简单地定义了一个类似StackPanel的布局控件,你还可以自定义更加复杂的布局控件,关于更复杂的自定义控件,你可以参考如下一些文章。在下面一篇文章将分享WPF中依赖属性的内容。
* [FishEyePanel/FanPanel](http://www.codeproject.com/Articles/15705/FishEyePanel-FanPanel-Examples-of-custom-layout-pa)
* [PlotPanel](http://msdn2.microsoft.com/en-us/library/ms771626.aspx), Windows SDK Sample
本文所有源码下载:[WPFLayouDemo.zip](http://files.cnblogs.com/zhili/WPFLayouDemo.zip)
- C# 基础知识系列
- C# 基础知识系列 专题一:深入解析委托——C#中为什么要引入委托
- C# 基础知识系列 专题二:委托的本质论
- C# 基础知识系列 专题三:如何用委托包装多个方法——委托链
- C# 基础知识系列 专题四:事件揭秘
- C# 基础知识系列 专题五:当点击按钮时触发Click事件背后发生的事情
- C# 基础知识系列 专题六:泛型基础篇——为什么引入泛型
- C# 基础知识系列 专题七: 泛型深入理解(一)
- C# 基础知识系列 专题八: 深入理解泛型(二)
- C# 基础知识系列 专题九: 深入理解泛型可变性
- C#基础知识系列 专题十:全面解析可空类型
- C# 基础知识系列 专题十一:匿名方法解析
- C#基础知识系列 专题十二:迭代器
- C#基础知识 专题十三:全面解析对象集合初始化器、匿名类型和隐式类型
- C# 基础知识系列 专题十四:深入理解Lambda表达式
- C# 基础知识系列 专题十五:全面解析扩展方法
- C# 基础知识系列 专题十六:Linq介绍
- C#基础知识系列 专题十七:深入理解动态类型
- 你必须知道的异步编程 C# 5.0 新特性——Async和Await使异步编程更简单
- 全面解析C#中参数传递
- C#基础知识系列 全面解析C#中静态与非静态
- C# 基础知识系列 C#中易混淆的知识点
- C#进阶系列
- C#进阶系列 专题一:深入解析深拷贝和浅拷贝
- C#进阶系列 专题二:你知道Dictionary查找速度为什么快吗?
- C# 开发技巧系列
- C# 开发技巧系列 使用C#操作Word和Excel程序
- C# 开发技巧系列 使用C#操作幻灯片
- C# 开发技巧系列 如何动态设置屏幕分辨率
- C# 开发技巧系列 C#如何实现图片查看器
- C# 开发技巧 如何防止程序多次运行
- C# 开发技巧 实现属于自己的截图工具
- C# 开发技巧 如何使不符合要求的元素等于离它最近的一个元素
- C# 线程处理系列
- C# 线程处理系列 专题一:线程基础
- C# 线程处理系列 专题二:线程池中的工作者线程
- C# 线程处理系列 专题三:线程池中的I/O线程
- C# 线程处理系列 专题四:线程同步
- C# 线程处理系列 专题五:线程同步——事件构造
- C# 线程处理系列 专题六:线程同步——信号量和互斥体
- C# 多线程处理系列专题七——对多线程的补充
- C#网络编程系列
- C# 网络编程系列 专题一:网络协议简介
- C# 网络编程系列 专题二:HTTP协议详解
- C# 网络编程系列 专题三:自定义Web服务器
- C# 网络编程系列 专题四:自定义Web浏览器
- C# 网络编程系列 专题五:TCP编程
- C# 网络编程系列 专题六:UDP编程
- C# 网络编程系列 专题七:UDP编程补充——UDP广播程序的实现
- C# 网络编程系列 专题八:P2P编程
- C# 网络编程系列 专题九:实现类似QQ的即时通信程序
- C# 网络编程系列 专题十:实现简单的邮件收发器
- C# 网络编程系列 专题十一:实现一个基于FTP协议的程序——文件上传下载器
- C# 网络编程系列 专题十二:实现一个简单的FTP服务器
- C# 互操作性入门系列
- C# 互操作性入门系列(一):C#中互操作性介绍
- C# 互操作性入门系列(二):使用平台调用调用Win32 函数
- C# 互操作性入门系列(三):平台调用中的数据封送处理
- C# 互操作性入门系列(四):在C# 中调用COM组件
- CLR
- 谈谈: String 和StringBuilder区别和选择
- 谈谈:程序集加载和反射
- 利用反射获得委托和事件以及创建委托实例和添加事件处理程序
- 谈谈:.Net中的序列化和反序列化
- C#设计模式
- UML类图符号 各种关系说明以及举例
- C#设计模式(1)——单例模式
- C#设计模式(2)——简单工厂模式
- C#设计模式(3)——工厂方法模式
- C#设计模式(4)——抽象工厂模式
- C#设计模式(5)——建造者模式(Builder Pattern)
- C#设计模式(6)——原型模式(Prototype Pattern)
- C#设计模式(7)——适配器模式(Adapter Pattern)
- C#设计模式(8)——桥接模式(Bridge Pattern)
- C#设计模式(9)——装饰者模式(Decorator Pattern)
- C#设计模式(10)——组合模式(Composite Pattern)
- C#设计模式(11)——外观模式(Facade Pattern)
- C#设计模式(12)——享元模式(Flyweight Pattern)
- C#设计模式(13)——代理模式(Proxy Pattern)
- C#设计模式(14)——模板方法模式(Template Method)
- C#设计模式(15)——命令模式(Command Pattern)
- C#设计模式(16)——迭代器模式(Iterator Pattern)
- C#设计模式(17)——观察者模式(Observer Pattern)
- C#设计模式(18)——中介者模式(Mediator Pattern)
- C#设计模式(19)——状态者模式(State Pattern)
- C#设计模式(20)——策略者模式(Stragety Pattern)
- C#设计模式(21)——责任链模式
- C#设计模式(22)——访问者模式(Vistor Pattern)
- C#设计模式(23)——备忘录模式(Memento Pattern)
- C#设计模式总结
- WPF快速入门系列
- WPF快速入门系列(1)——WPF布局概览
- WPF快速入门系列(2)——深入解析依赖属性
- WPF快速入门系列(3)——深入解析WPF事件机制
- WPF快速入门系列(4)——深入解析WPF绑定
- WPF快速入门系列(5)——深入解析WPF命令
- WPF快速入门系列(6)——WPF资源和样式
- WPF快速入门系列(7)——深入解析WPF模板
- WPF快速入门系列(8)——MVVM快速入门
- WPF快速入门系列(9)——WPF任务管理工具实现
- ASP.NET 开发
- ASP.NET 开发必备知识点(1):如何让Asp.net网站运行在自定义的Web服务器上
- ASP.NET 开发必备知识点(2):那些年追过的ASP.NET权限管理
- ASP.NET中实现回调
- 跟我一起学WCF
- 跟我一起学WCF(1)——MSMQ消息队列
- 跟我一起学WCF(2)——利用.NET Remoting技术开发分布式应用
- 跟我一起学WCF(3)——利用Web Services开发分布式应用
- 跟我一起学WCF(3)——利用Web Services开发分布式应用
- 跟我一起学WCF(4)——第一个WCF程序
- 跟我一起学WCF(5)——深入解析服务契约 上篇
- 跟我一起学WCF(6)——深入解析服务契约 下篇
- 跟我一起学WCF(7)——WCF数据契约与序列化详解
- 跟我一起学WCF(8)——WCF中Session、实例管理详解
- 跟我一起学WCF(9)——WCF回调操作的实现
- 跟我一起学WCF(10)——WCF中事务处理
- 跟我一起学WCF(11)——WCF中队列服务详解
- 跟我一起学WCF(12)——WCF中Rest服务入门
- 跟我一起学WCF(13)——WCF系列总结
- .NET领域驱动设计实战系列
- .NET领域驱动设计实战系列 专题一:前期准备之EF CodeFirst
- .NET领域驱动设计实战系列 专题二:结合领域驱动设计的面向服务架构来搭建网上书店
- .NET领域驱动设计实战系列 专题三:前期准备之规约模式(Specification Pattern)
- .NET领域驱动设计实战系列 专题四:前期准备之工作单元模式(Unit Of Work)
- .NET领域驱动设计实战系列 专题五:网上书店规约模式、工作单元模式的引入以及购物车的实现
- .NET领域驱动设计实战系列 专题六:DDD实践案例:网上书店订单功能的实现
- .NET领域驱动设计实战系列 专题七:DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能
- .NET领域驱动设计实战系列 专题八:DDD案例:网上书店分布式消息队列和分布式缓存的实现
- .NET领域驱动设计实战系列 专题九:DDD案例:网上书店AOP和站点地图的实现
- .NET领域驱动设计实战系列 专题十:DDD扩展内容:全面剖析CQRS模式实现
- .NET领域驱动设计实战系列 专题十一:.NET 领域驱动设计实战系列总结