一起学WPF系列(3):窗体

概述

Windows Presentation Foundation (WPF) 是下一代显示系统,用于生成能带给用户震撼视觉体验的 Windows 客户端应用程序。使用 WPF,您可以创建广泛的独立应用程序以及浏览器承载的应用程序。一直以来,我对界面的东西是不怎么感兴趣的,可自从Windows Presentation Foundation (WPF)发布之后,也不免为它能实现的绚丽的界面所吸引,《一起学WPF系列》和大家一起分享学习WPF学习经验的系列文章。

本文是《一起学WPF系列》中的第三篇,开始学习WPF的基础知识.

本文目的:

学习和掌握WPF中窗体的构成,创建方式,生命周期,位置,大小,状态,外观等控制方式。

窗体构成:

窗体是WPF中最重要的一个呈现控件,它能够容纳其他的WPF控件,用户通常也是通过窗口来与WPF应用程序进行数据交互的。而一个WPF窗体被分为两个区域:客户区和非客户区。它的构成图如下:

非客户端包括普通窗体的通用组成部分,它们为:

  1. 边框(Border)
  2. 标题栏(Title Bar)
  3. 图标(Icon)
  4. 最大化,最小化,还原,关闭按钮
  5. 系统菜单

而客户端,我们也可以称之为工作区,它是用于供开发人员自定义内容的区域。在WPF中,窗体的实现类为:System.Windows.Window.它在架构中层次结构如下图所示:

由层次结构中可以看出,窗体也是一种控件。它们与Button,UserControl等同属于WPF架构中的FrameworkElement.

创建方式:

如果在创建项目的时候,选择的是WPF Application项目模板,那么在项目创建完成之后,便会有一个名为Window1的窗体。这个在上文我们已经有所体验,如果需要添加新的窗体,可以在资源管理器中右击项目,然后选择Add-Window..,如下图所示:

如果要使用XAML来创建窗体,代码如下:

<Window x:Class="Jillzhang.Wpf.WindowStudy.Window1" 

xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" > 

</Window> 

窗体的后台代码为:

/// <summary> 

/// Interaction logic for Window1.xaml 

/// </summary> 


public partial class Window1 : Window 



public Window1() 



InitializeComponent(); 

}
 

}
 

下面的列表是对XAML文件的解析

名称

类型

说明

Window

元素(Element)

用于声明一个WPF窗体

x:Class

属性(必须)

指示窗体对应的的类,它继承于System.Windows.Window

xmlns

属性(必须)

XAML命名空间

xmlns:x

属性必须

XAML架构中的x:的命名空间

x:Class指示的类默认情况下是使一个partical 类,它的构造函数必须包含InitializeComponent();

生命周期:

窗口的生命周期对编程的时候影响甚大,如果不清楚窗口的生命周期,一不小心很可能就引发对象空引用的错误,一个窗体它的生命周期图如下:

首先我们先来看看打开窗体的步骤,要想在应用程序中打开一个窗体,必须先创建窗体的对象实例,方法有两个: 1)通过StartupUri来设定2)通过编程方式来实现。第一种方式我们在上文中已经提到过,第二种方式可书写代码如下:

Window1 window = new Window1(); 
window.Show(); 

注意如果是在Application的Startup事件中实例化窗口,窗口引用会自动添加到Applicaton.Windows集合中,并且第一个实例化的窗口被当成Application.MainWindow。在调用Show()方法进行窗体显示之前,窗体会进行初始化工作,此时会引发SourceInitialized事件,此后呈现窗体,当窗体第一次显示,便引发窗体的Activated事件,使得该窗体称为活动窗体,活动窗体能够接受用户输入,激活窗口操作完成之后,窗体的Load事件才会被触发,其后引发ContentRendered事件,当ContentRendered引发后表示窗体已经被打开。而此时,如果切换了窗体,那么原本的活动窗口便会引发Deactivated事件,而切换到的窗口引发Activated事件。窗体是否处于活动状态,可以通过IsActive属性来确定。下面看一下窗体的关闭过程,点击非客户区的关闭按钮或者用系统热键Alt+F4,调用窗体的Close()方法或者用其他方式关闭窗体的时候,都会触发窗体的Closing事件和Closed事件。Closing在窗口关闭之前,用于提供一种机制用于阻止窗口关闭,比如关闭之前检查数据是否已经被成功提交从而决定关闭操作是否继续。如果要阻止关闭窗口,可以将Closing事件的CacelEventArg参数的Cacel属性为True。在Closing中没有被取消的窗体将触发Closed事件。

注:虽然msdn上窗体事件的执行顺序如上图所示,可我测试过的结果和上图略有差异,就是Loaded的位置,我测试的结果如下图所示:

我的测试结果效果为:

这和msdn的说明不太一致,搞不明白为何!不过我相信我的测试结果应该是正确的

起始位置:

窗口的起始位置可以通过WindowStartupLocation属性来确定,他们的可选选项为:

位置

说明

CenterOwner

所有者的中间位置

CenterScreen

屏幕的中间位置

Manual

根据Left和Top来确定起始位置,如果没有设置,将由Windows决定位置

 另外,窗口还有Z-Order和Topmost属性用于设置窗体在Z轴上的位置。设置了Topmost的窗体将无法被其他窗体覆盖。当主窗体Topmost属性为false的效果为:

而主窗体的Topmost为true时,效果为:

大小:

窗体的大小由Width和Height或者用SizeToContent来决定 ,SizeToContent包括四个选项

选项

说明

Height

窗体只自动适应内容高度

Width

窗体只自动适应内容长度

Manual

窗体大小由windows来决定

WidthAndHeight

窗体自动适应内容长度和高度

 状态:

窗体状态有如下三种:

状态

说明

Normal

正常窗体

Maximized

最大化

Minimized

最小化

 外观:

窗体样式包括四个:

窗体样式

说明

None

不包括非客户区的标题栏,系统菜单,最大,最小,关闭按钮,图标等

SingleBorderWindow

普通边框

ThreeDBorderWindow

3D边框

ToolWindow

不包括图标,最大,最小化按钮

 

 范例项目

 /Files/jillzhang/Jillzhang.Wpf.WindowStudy.rar

结束语

WPF中的窗口与 Window Form基本相似,但增加了一些额特殊功能,文中有关事件执行顺序我现在还有疑惑,因为我测试结果和msdn说明不太一致,希望明白人指点一二,不胜感激

 

作者:jillzhang
出处:http://jillzhang.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
标签: WPF
posted @ 2008-04-05 20:10 Robin Zhang 阅读(21693) 评论(27) 编辑 收藏

 回复 引用 查看   
#1楼 2008-04-05 20:19 李涛      
好快,已经到三了,辛苦了!
 回复 引用 查看   
#2楼 2008-04-05 20:46 生鱼片      
楼主的精力真是令人敬佩啊
 回复 引用   
#3楼 2008-04-05 23:18 VS2005新手[未注册用户]
太超前了,不过顶一下!!
 回复 引用 查看   
#4楼 2008-04-06 07:45 王德水      
虽然和winform里很多概念相同,楼主这样能写的这么清楚,确实厉害,最近也开始学习wpf,支持JillZhang,
 回复 引用   
#5楼 2008-04-06 10:15 KEN-张[未注册用户]
还没试过WPF,但感觉很炫,不过我首选的还是性能,不知它与传统WINFORM相比性能如何?
 回复 引用 查看   
#6楼 2008-04-06 10:17 陈旭85      
支持,目前机子还装不了08,换新机后慢慢看
 回复 引用 查看   
#7楼 2008-04-07 10:40 球球      
msdn应该是正确的,我做了下试验,showdialog和show都用了,结果和msdn相同,不过我的系统是XP。
顺便问个问题,我用showdialog打开一个窗体,然后点主窗体无法获得焦点,这个是正确的,但是如果这时访问另一个应用程序界面,比如IE,回头点用showdialog打开的窗体,那么就会只显示这个窗体,而主窗体没有显示出来(虽然主窗体仍然无法获得焦点)......这个问题应该是怎么解决的。

 回复 引用 查看   
#8楼[楼主] 2008-04-07 11:15 jillzhang      

可是我在win2003下测试结果仍然和vista一致


 回复 引用 查看   
#9楼 2008-04-07 13:37 球球      

方法应该都差不多吧。我的结果截然不同........


 回复 引用   
#10楼 2008-04-07 15:43 Ian[未注册用户]
不管质量如何,能看出来楼主写的很认真,支持下
 回复 引用 查看   
#11楼 2008-04-07 15:50 Kingthy      
我测试的是同MSDN一样的:

SourceInitialized
Activated
Loaded
ContentRendered
Closing
Deactivated
Closed

测试系统为Win2003,代码如下,运行后窗体显示完全后关闭就得到上面的数据:

///
/// Window1.xaml 的交互逻辑
///

public partial class Window1 : Window
{
public Window1()
{
this.Activated += new EventHandler(Window1_Activated);
this.Closing += new System.ComponentModel.CancelEventHandler(Window1_Closing);
this.ContentRendered += new EventHandler(Window1_ContentRendered);
this.Deactivated += new EventHandler(Window1_Deactivated);
this.Loaded += new RoutedEventHandler(Window1_Loaded);
this.Closed += new EventHandler(Window1_Closed);
this.Unloaded += new RoutedEventHandler(Window1_Unloaded);
this.SourceInitialized += new EventHandler(Window1_SourceInitialized);

InitializeComponent();
}

void Window1_Unloaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Unloaded");
}

void Window1_SourceInitialized(object sender, EventArgs e)
{
Debug.WriteLine("SourceInitialized");
}

void Window1_Loaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Loaded");
}

void Window1_Deactivated(object sender, EventArgs e)
{
Debug.WriteLine("Deactivated");
}

void Window1_ContentRendered(object sender, EventArgs e)
{
Debug.WriteLine("ContentRendered");
}

void Window1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Debug.WriteLine("Closing");
}

void Window1_Closed(object sender, EventArgs e)
{
Debug.WriteLine("Closed");
}

void Window1_Activated(object sender, EventArgs e)
{
Debug.WriteLine("Activated");
}
}

 回复 引用 查看   
#12楼[楼主] 2008-04-07 16:20 jillzhang      
<Window x:Class="Jillzhang.Wpf.WindowStudy.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" WindowStyle="ToolWindow"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  WindowStartupLocation="CenterScreen" Topmost="False"
    Title="一起学WPF系列(3):主窗体" SizeToContent="WidthAndHeight"  Activated="Window_Activated" Loaded="Window_Loaded" Closing="Window_Closing"
        Unloaded="Window_Unloaded"  Deactivated="Window_Deactivated" SourceInitialized="Window_SourceInitialized" ContentRendered="Window_ContentRendered" Closed="Window_Closed">   
--------------------------------------------------------------------------------

   private void Window_Activated(object sender, EventArgs e)
        {
            if (statusBar1.Content.ToString().IndexOf("->Activated") == -1)
            {
                System.Diagnostics.Debug.WriteLine( "->Activated");
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("->Loaded");
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            MessageBoxResult dr = MessageBox.Show("要退出么?", "询问", MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (dr == MessageBoxResult.No)
            {
                e.Cancel = true;
            }
        }

        private void Window_Unloaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("->Unloaded");
        }

        private void Window_Deactivated(object sender, EventArgs e)
        {
            if (statusBar1.Content.ToString().IndexOf("->Deactivated") == -1)
            {
               System.Diagnostics.Debug.WriteLine("->Deactivated");
            }
        }

        private void Window_SourceInitialized(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("->SourceInitialized");
        }

        private void Window_ContentRendered(object sender, EventArgs e)
        {
           System.Diagnostics.Debug.WriteLine("->ContentRendered");
        }

        private void MenuItem_Click_1(object sender, RoutedEventArgs e)
        {
            Window2 w = new Window2();
            w.Show();
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine("->Closed");
        }


--------------------------------------------------------------------------------
结果还是

 回复 引用 查看   
#13楼 2008-04-18 15:08 good man      
学习了,有了入门,
支持

 回复 引用   
#14楼 2008-05-20 13:11 baobaoyan[未注册用户]
正在学习中谢谢哈哈!!!
 回复 引用 查看   
#15楼 2008-06-04 16:01 英雄      
谢谢,楼主!学习中。。。
 回复 引用 查看   
#16楼[楼主] 2008-06-04 18:29 jillzhang      
@英雄
共同学习

 回复 引用   
#17楼 2008-06-23 16:43 Wind19842004[未注册用户]
写的很棒 通俗易懂 支持下楼主
 回复 引用   
#18楼 2008-08-24 19:00 郭涛[未注册用户]
using system;
using system.windows;
namepace petzold.sayhello
{
class sayhello
{
[STATHread]
public static void main()
{
window win=new window();
win.Title="say hello";
win.show();
application app=new application();
app.run();
}
}
}
这是个wpf框架的应用程序 你能j交交我怎么用vs2008中编译么
我非常想知道的

 回复 引用   
#19楼 2008-08-24 19:04 郭涛[未注册用户]
请楼主尽快的帮帮忙啊
 回复 引用 查看   
#20楼[楼主] 2008-08-25 16:23 jillzhang      
@郭涛
建立项目后,生成就可以了

 回复 引用   
#21楼 2008-12-05 06:54 小毛孩儿[未注册用户]
最近在跟外教学习WCF,WPF,还有Project要做,头大...
幸好有中文相应材料~
受益非浅
致谢!

 回复 引用 查看   
#22楼[楼主] 2008-12-05 09:36 jillzhang      
@小毛孩儿
共同学习

 回复 引用   
#23楼 2009-06-24 15:13 wpfsl[未注册用户]
支持楼主




------
欢迎加入 WPF Silverlight 技术超级群
1群: 10458228 (500 人,已满)
2群: 13598877 (383 人/500 人)

群里气氛活跃并有大量学习资源

 回复 引用 查看   
#24楼 2009-06-26 10:28 ▄︻┻┳═一      
88154583 WPF技术交流 有空来坐坐

 回复 引用 查看   
#25楼 2010-04-14 18:31 黑子范      
怎么只到3就没了,期待你的后续》。。
 回复 引用 查看   
#26楼 2010-05-18 22:24 zhanxp      
哈哈 Robin开始搞WPF了啊
 回复 引用 查看   
#27楼 2011-01-12 15:46 酸枣茶      
试试