WPF开发入门尝试

开发 后端
本文将从一个WPF软件雏形谈到如何制作一个组件,包括最后的运行结果。希望给那些对WPF有兴趣的程序员参考。

  01. 创建软件雏形

  这个雏形包括4个项目(Project):

  一个主程序(WPF Application)项目,命名为:DataTracer

  一个组件库(WPF User Control Library)项目,命名为:K3UcLib

  一个控件库(WPF Custom Control Library)项目,命名为:K3CcLib

  一个算法库(Class Library)项目,命名为:K3Helper

  作为入门,这看起来有点复杂,不过实现起来还算简单。

  菜单:File >New >Project…

  菜单:File >Add >New Project…

  THINKING:

  通常,复杂是由简单构成的,只要我们合理的分解它;

  复杂的设计,并不意味着复杂的实现;同样,简单的设计,也不意味着简单的实现;

  不过,没有准备迎接复杂挑战的简单设计,却通常是小小噩梦的开始。

  F5 运行,看看结果!

  02. 制作一个组件

  我习惯将User Control称为组件,将Custom Control称为控件。

  他们的区分,简单说:User Control通常通过组合多个控件产生,Custom Control通常通过扩展单个控件产生。

  现在,我们先制作一个准备用来替换现有窗口标题的组件,命名为:K3WindowHeader。

  Project Add User Control,然后修改XAML,并编译(Shift F6)

 

  1.   <Border CornerRadius="0, 0, 10, 10" Background="DarkBlue"> 
  2.   <DockPanel LastChildFill="True"> 
  3.   <Button Content="关闭" Width="75" Height="23" DockPanel.Dock="Right" /> 
  4.   <TextBlock Text="Window Header" DockPanel.Dock="Left" Foreground="White"/> 
  5.   </DockPanel> 
  6.   </Border> 

 

  这个组件包括两个控件Button,TextBlock。

  CornerRadius用于设定Border四个角的弧度

  = ”LeftTop, RightTop, RightBottom, LeftBottom”

  DockPanel.LastChildFill,很有用的属性。

  注意DockPanel所包含组件的顺序,并在组件中正确的使用DockPanel.Dock属性。

  在DataTracer中使用这个组件。

  Project Add References,添加K3UcLib,然后修改MainWindow.XAML:

 

  1.   <Window …  
  2. xmlns:K3UcLib="clr-namespace:K3UcLib;assembly=K3UcLib" 
  3. WindowStyle="None" 
  4. >  xmlns:K3UcLib="clr-namespace:K3UcLib;assembly=K3UcLib" 
  5.   WindowStyle="None" 
  6.   >  xmlns:K3UcLib="clr-namespace:K3UcLib;assembly=K3UcLib" 
  7.   WindowStyle="None" 
  8.   > 
  9.   <Grid> 
  10.   <Grid.RowDefinitions> 
  11.   <RowDefinition Height="Auto"/> 
  12.   <RowDefinition Height="*"/> 
  13.   <RowDefinition Height="Auto"/> 
  14.   </Grid.RowDefinitions> 
  15.   <K3UcLib:K3WindowHeader Height="25" /> 
  16.   </Grid> 

 

  将WindowStyle设为None,将窗口标题隐掉,从而为DIY新的窗口标题做好准备。

  Height, Width可取值包括:

  Auto(自适应),*(全部剩余),NaN(相当于Auto),数值

  F5 运行,看看结果!

  这个窗口怎么关掉?Alt + F4!

  这个窗口好丑!别着急,如果你真的很急,可以先试着使用 Margin属性及xxxAlignment属性,调整一下位置(试一试我的调整,如下)。

 

  1.   <Border CornerRadius="0, 0, 10, 10" Background="DarkBlue" Margin="3,0,3,0"> 
  2.   <DockPanel LastChildFill="True"> 
  3.   <Button Content="关闭" Width="75" Height="23" DockPanel.Dock="Right" Margin="0, 0, 10, 0" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
  4.  <TextBlock Text="Window Header" DockPanel.Dock="Left" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" /> 
  5.   </DockPanel> 
  6.   </Border> 

 

  F5 运行,看看结果!

  

  03. 添加事件,关闭窗口

  需求:当用户点击“关闭”按钮时,关闭主窗口。

  实现:为“关闭”按钮添加Click事件处理。有两种实现方式:

  (1) 通过XAML文件中实现:<Button Name=”buttonClose” Content=”” ……Click=”buttonClose_Click” ……/>

  (2) 通过后台代码实现:this.buttonClose.Click += new new RoutedEventHandler(buttonClose_Click);

  这里,我们采用后者,即后台代码方式,完整代码如下:

 

  1.   public K3WindowHeader() {  
  2.   InitializeComponent();  
  3.   this.Init();  
  4.   }  
  5.   void Init() {  
  6.   this.buttonClose.Click += new RoutedEventHandler(Button_Click);  
  7.   }  
  8.   void Button_Click(object sender, RoutedEventArgs e) {  
  9.   throw new NotImplementedException();  
  10.   } 

 

  注:

  使用Init()方法,是为了使代码整洁。

  在你键入“+=”时,系统将为你自动生成事件代码。你可以先修改所生成的事件处理方法的名字,然后再按“TAB”键,这样就可以生成你想要的名字的方法。在这里,我将默认的buttonClose_click改为Button_Click。

  接下来,我们添加事件处理的内容,以实现关闭主窗体。

  注意,因为我们使用的是另一个组件项目中的组件,而非主程序自身项目中的组件,所以实现起来稍微有点麻烦,不是简单的一个Close()就可以完成。

  在这种情况下,有多重实现方式:

  (1) 假定组件自身知道自己是如何被使用的,如本案例中,它被放在主窗体的Grid中,那么可以这样实现:

  ((this.Parent as Grid).Parent as Window).Close(); 这种实现方式,属于hard code,使组件失去了灵活性,不是一个好方法,但它是一个思路,即:只要你能找到你想要的,你就可以做你想做的。

  (2) 将点击“关闭”按钮事件,转化成一个新的事件,告诉引用这个组件的窗体:有人请求关掉你!这个设计有点麻烦,但使组件具有了组件该有的特性:灵活性,或称为适应性,以保证你可以相对随意的使用它。

  

 

#region >>>>> 自定义事件 ...

public static readonly RoutedEvent PreviewWindowHeaderEvent;

public event RoutedEventHandler PreviewWindowHeaderEventHandler {

add { this.AddHandler(PreviewWindowHeaderEvent, value); }

remove { this.RemoveHandler(PreviewWindowHeaderEvent, value); }

}

static K3WindowHeader() {

PreviewWindowHeaderEvent = EventManager.RegisterRoutedEvent(

"PreviewWindowHeaderEventHandler",

RoutingStrategy.Tunnel,

typeof(RoutedEventHandler),

typeof(K3WindowHeader));

}

#endregion

……

void Button_Click(object sender, RoutedEventArgs e) {

RoutedEventArgs eventArgs = new RoutedEventArgs();

eventArgs.RoutedEvent = PreviewWindowHeaderEvent;

RaiseEvent(eventArgs);

}

这段代码,加在K3WindowHeader中。

#region #endregion的合理使用,有利于提升代码的可读性。你可以加上注释。BTW,我添加>>>>> … 是为了美观,读者可以试试去掉它,或改变它,看看你自己更喜欢哪一个。

注意,我添加了static 类型的构造函数,以便注册自定义事件。

Event有两种类型,其关键参数是:RoutingStrategy,其取值的不同,将生成两种传递方向不同事件。详述如下:

     
 

public static readonly RoutedEvent PreviewWindowHeaderEvent;

public event RoutedEventHandler PreviewWindowHeaderEventHandler {

add { this.AddHandler(PreviewWindowHeaderEvent, value); }

remove { this.RemoveHandler(PreviewWindowHeaderEvent, value); }

}

static MainWindow() {

PreviewWindowHeaderEvent = K3WindowHeader.PreviewWindowHeaderEvent.AddOwner(typeof(MainWindow));

}

void Init() {

this.PreviewWindowHeaderEventHandler += new RoutedEventHandler(CustomEventHandler);

}

void CustomEventHandler(object sender, RoutedEventArgs e) {

this.Close();

}

这段代码,加在DataTracer中。

注意这段代码与上段代码的不同,在于静态构造中,我们通过事件的AddOwner方法,将这两个自定义事件关联起来,从而保证了可以捕获到该事件。

同样,我使用了Init来使代码整洁,并在其中添加了对该特定事件的处理程序。别忘了将Init()放入构造函数中。

 

  F5 运行,看看结果!

原文链接:http://www.cnblogs.com/technology/archive/2011/04/19/2020910.html

【编辑推荐】

  1. 深入浅出WPF
  2. 教你制作一个简单的WPF图片浏览器
  3. WPF中两种不同的视频流的使用
  4. 新版本WPF功能 彰显赏心悦目的图形
  5. C++实现WPF动画具体操作方法详解

责任编辑:彭凡 来源: 博客园
相关推荐

2009-07-16 16:01:54

WebWork敏捷开发

2009-12-24 18:09:23

WPF开发环境

2019-05-17 14:55:08

优化图形差距

2009-12-29 14:58:31

WPF优点

2009-12-23 09:18:39

WPF开发工具

2009-12-29 15:14:16

WPF开发工作站

2009-12-25 15:12:01

WPF平台

2009-04-07 09:28:39

.NETWPF数据虚拟化

2016-04-22 09:40:24

2023-10-16 08:00:00

2023-02-19 09:02:22

2010-03-01 13:50:35

Visual Stud

2009-07-22 17:07:16

WPF插件开发.NET Framew

2011-09-09 14:09:17

Android Wid

2009-10-21 12:45:07

linux程序开发基础入门

2022-10-12 15:00:02

设备开发应用开发

2010-07-02 09:54:32

Symbian开发

2023-02-08 16:20:39

2013-04-08 14:12:03

Android开发googleMap入门SDK

2011-05-03 15:13:23

BlackBerryWidget
点赞
收藏

51CTO技术栈公众号