谈基于net平台windows开发中的模式窗体Word格式文档下载.docx
《谈基于net平台windows开发中的模式窗体Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《谈基于net平台windows开发中的模式窗体Word格式文档下载.docx(14页珍藏版)》请在冰豆网上搜索。
![谈基于net平台windows开发中的模式窗体Word格式文档下载.docx](https://file1.bdocx.com/fileroot1/2022-12/8/08f575b5-33da-456f-a999-dc96d5319ec4/08f575b5-33da-456f-a999-dc96d5319ec41.gif)
选项打开的那个选项对话框为例,对于设计器初始化的窗体还是需要进行一番设置才能达到专业化。
令人高兴的是这些设置都可以在设计器模式中通过属性设置实现,笔者将通过代码来实现相应功能,下面对其进行详细描述。
Form.StartPosition属性,确定窗体第一次出现时的位置。
这里设置为在父窗体的中间显示。
this.StartPosition=FormStartPosition.CenterParent;
Form.HelpButton属性,确定窗体的标题栏上是否有“帮助”按钮。
设置显示,看上去更人性化,但实际不一定会对帮助功能进行实现。
this.HelpButton=true;
Form.MaximizeBox属性,确定窗体标题栏的右上角是否有最大化框。
设置不让她显示。
this.MaximizeBox=false;
Form.MinimizeBox属性,确定窗体标题栏的右上角是否有最小化框。
设置不让他显示。
this.MinimizeBox=false;
Form.ShowIcon属性,指示是否在窗体的标题栏中显示图标。
设置不显示。
this.ShowIcon=false;
Form.ShowInTaskbar属性,确定窗体是否出现在Windows任务栏中。
这个当然要节省任务栏的宝贵空间。
this.ShowInTaskbar=false;
Form.FormBorderStyle属性,指示窗体的边框和标题栏的外观和行为。
设置这个属性将不允许拖动调整窗体的大小,同时Icon属性将失效,并不显示窗体标题栏图片。
this.FormBorderStyle=FormBorderStyle.FixedDialog;
Form.ControlBox属性,确定窗体是否有“控件/系统”菜单框。
通过该设置可以隐藏标题栏的控制按钮。
在有些时候还是有必要设置为False,标题栏就不会再有控制按钮。
this.ControlBox=false;
通过对以上属性的设置,基本实现模式窗体的静态功能。
对于是否允许调整窗体的大小可根据实际情况而定。
模式窗体中(比如visualstudio2005中的“选项”对话框)一般会有两个基本按钮,一个[确定]按钮用来提交,另一个[取消]按钮用来撤销提交,有时候会增加一个[应用]按钮,不过像“帮助”菜单中的“关于”模式窗体可能就只有一个[确定]按钮。
Windows窗体为用户操作友好性提供了比较好的支持。
我们可以在Form设计界面的属性设置中找到AcceptButton和CancelButton两个属性,默认值为空即显示(无)。
在属性中可以通过选择窗体上的按钮来设置值。
属性修改生成的代码如下。
先定义两个Button,
privateSystem.Windows.Forms.ButtonbuttonOK;
privateSystem.Windows.Forms.ButtonbuttonCancel;
窗体的“接受”按钮。
如果设置了此按钮,则用户每次按“Enter”键都相当于“单击”了该按钮。
this.AcceptButton=this.buttonOK;
窗体的“取消”按钮。
如果设置了此按钮,则用户每次按“Esc”键都相当于“单击”了该按钮。
this.CancelButton=this.buttonCancel;
可见可以通过快捷键来方便的访问特定按钮,但这个有一些例外,比如窗体焦点刚好在buttonCancel上,当按{Enter}时实际按下的键会是buttonCancel而不是buttonOK,如果焦点停在第三个按钮上,那{Enter}按下相当于点击了该按钮。
另一个细节是通过鼠标点击按钮和快捷键操作按钮的表现行为不一样,快捷键操作Button不会显示按钮被按下的显示效果,看上去什么都没有发生。
谈到模式窗体的打开,一般通过Form.ShowDialog()方法或她的一个重载Form.ShowDialog(IWin32Window)来实现,其中后一个方法将窗体显示为具有指定所有者的模式对话框。
如下代码所示,
OptionFormform=newOptionForm();
//form.ShowDialog();
form.ShowDialog(this);
对于指定所有者方式打开的模式窗体可以在模式窗体内部获取主窗体的引用,
//在模式窗体内部访问所属窗体
MainFormform=this.OwnerasMainForm;
注意,如果以Form.ShowDialog()方式打开,那Form.Owner属性会是空引用。
谈到模式窗体的关闭,先来看一下模式窗体关闭后的返回值。
无论是调用Form.ShowDialog()方法还是Form.ShowDialog(IWin32Window)方法,都会在模式窗体关闭时返回System.Windows.Forms.DialogResult枚举值。
参考MSDN,该枚举包含的值如下,
DialogResult.Abort,对话框的返回值是Abort(通常从标签为“中止”的按钮发送)。
DialogResult.Cancel,对话框的返回值是Cancel(通常从标签为“取消”的按钮发送)。
DialogResult.Ignore,对话框的返回值是Ignore(通常从标签为“忽略”的按钮发送)。
DialogResult.No,对话框的返回值是No(通常从标签为“否”的按钮发送)。
DialogResult.None,从对话框返回了Nothing。
这表明有模式对话框继续运行。
DialogResult.OK,对话框的返回值是OK(通常从标签为“确定”的按钮发送)。
DialogResult.Retry,对话框的返回值是Retry(通常从标签为“重试”的按钮发送)。
DialogResult.Yes,对话框的返回值是Yes(通常从标签为“是”的按钮发送)。
由于某些原因在实际用户操作中比如选项数据无法保存,输入的设置数据有问题,点击[确定]按钮需要阻止窗体的关闭以对输入的设置进行调整。
对于一些开发者在技术社区贴的阻止模式窗体关闭的代码,我认为不是很好的实现。
以下用代码来描述该实现,注意其中用到了三个事件。
//注册窗体关闭事件
this.FormClosing+=newSystem.Windows.Forms.FormClosingEventHandler(this.OptionForm_FormClosing);
//注册确定按钮事件
this.buttonOK.Click+=newSystem.EventHandler(this.buttonOK_Click);
//注册取消按钮事件
this.buttonCancel.Click+=newSystem.EventHandler(this.buttonCancel_Click);
三个事件对应的事件处理程序如下,
//确定按钮处理程序
privatevoidbuttonOK_Click(objectsender,EventArgse)
{
//假设textBoxPath用来记录目录路径,如果不存在要求用户重新设置。
if(this.textBoxPath.Text.Trim().Length==0)
{
MessageBox.Show("
输入路径信息不对!
"
);
this.textBoxPath.Focus();
}
else
this.DialogResult=DialogResult.OK;
}
//取消按钮处理程序
privatevoidbuttonCancel_Click(objectsender,EventArgse)
this.DialogResult=DialogResult.Cancel;
//窗体关闭处理程序,在关闭窗体时发生。
privatevoidOptionForm_FormClosing(objectsender,FormClosingEventArgse)
if(this.DialogResult!
=DialogResult.Cancel&
&
this.DialogResult!
=DialogResult.OK)
e.Cancel=true;
上面的代码都正常,就是事件写多了,对上面代码进行修改,去掉[取消]按钮事件和窗体关闭事件以及相关的事件处理程序。
首先需要在窗体构造函数中通过设置按钮的DialogResult属性来实现返回特定的DialogResult。
this.buttonOK.DialogResult=System.Windows.Forms.DialogResult.OK;
this.buttonCancel.DialogResult=System.Windows.Forms.DialogResult.Cancel;
注册确定按钮事件,
输入的路径信息不对!
//设置文本框焦点
this.DialogResult=DialogResult.None;
可见,新的实现方式代码减少了一半。
对于窗体间的数据传递,是刚开始从事.Net窗体应用程序开发人员碰到的一个常见问题,在此讲几个常见的实现方式。
此节内容适用于模式窗体或非模式窗体,部分方式延伸到一般类的操作。
(1)构造函数参数传递
通过构造函数传递参数应该是比较基本的参数传递方式,重载构造函数,通过带参数的构造函数来实例化窗体。
在窗体类内部定义参数变量,
privateobjectmyParams;
实现构造函数,
publicOptionForm(objectparameters)
InitializeComponent();
this.myParams=parameters;
//设置参数引用
实例化窗体,
OptionFormform=newOptionForm(myParams);
在实际使用过程中,需要注意传入的是引用类型还是值类型,处理方式会有所不同。
(2)使用窗体的属性
说起属性关联,上面已经提到过Form.Owner属性,下面笔者根据MSDN文档来比较完整的讲一下,大部分的文字来自MSDN文档,为保证其完整性,对其中一些属性描述进行了扩展。
Form.Owner属性。
获取或设置拥有此窗体的窗体。
语法,publicFormOwner{get;
set;
若要使某窗体归另一个窗体所有,可为其Owner属性分配一个对将成为所有者的窗体的引用。
当一个窗体归另一窗体所有时,它便随着所有者窗体最小化和关闭。
例如,如果Form2归窗体Form1所有,则关闭或最小化Form1时,Form2也会关闭或最小化。
并且附属窗体从不显示在其所有者窗体后面。
可以将附属窗体用于查找和替换窗口之类的窗口,当选定所有者窗体时,这些窗口不应消失。
Form.OwnedForms属性。
获取Form对象的数组,这些对象表示此窗体拥有的所有窗体。
语法,publicForm[]OwnedForms{get;
此属性返回包含此窗体拥有的所有窗体的数组。
要使某窗体归另一个窗体所有,可调用AddOwnedForm方法。
分配给所有者窗体的窗体将保持被拥有状态,直到调用了RemoveOwnedForm方法。
如果窗体是多文档界面(MDI)父窗体,则除了当前打开的所有MDI子窗体外,此属性将返回所有显示的窗体。
Form.MdiChildren属性。
获取窗体的数组,这些窗体表示以此窗体作为父级的多文档界面(MDI)子窗体。
语法,publicForm[]MdiChildren{get;
此属性使您得以获取对当前在某MDI父窗体中打开的所有MDI子窗体的引用。
若要创建MDI子窗体,请将要成为MDI父窗体的Form分配给该子窗体的MdiParent属性。
可以使用此属性依次通过所有MDI子窗体,以执行一些操作,如当MDI父窗体关闭时将数据保存到数据库中,或者根据应用程序中执行的操作更新子窗体上的字段。
Form.MdiParent属性。
获取或设置此窗体的当前多文档界面(MDI)父窗体。
语法,publicFormMdiParent{get;
可以从某MDI子窗体使用此属性来获取所有子窗体都需要的全局信息或者调用对所有子窗体执行操作的方法。
Form.ActiveForm静态属性。
获取此应用程序的当前活动窗体。
语法,publicstaticFormActiveForm{get;
表示当前活动窗体,或者如果没有活动窗体,则为空引用。
可以使用此方法获得对当前活动窗体的引用,以在该窗体或其控件上执行操作。
Form.ActiveMdiChild属性。
获取当前活动的多文档界面(MDI)子窗口。
语法,publicFormActiveMdiChild{get;
返回表示当前活动的MDI子窗口的Form,或者如果当前没有子窗口,则返回空引用。
可使用此方法确定MDI应用程序中是否有任何打开的MDI子窗体。
也可使用此方法从MDI子窗口的MDI父窗体或者从应用程序中显示的其他窗体对该MDI子窗口执行操作。
ContainerControl.ParentForm属性。
获取将容器控件分配给的窗体。
语法,publicFormParentForm{get;
将容器控件分配给的Form。
以上属性MSDN提供相应的代码事例,可直接拿来调试使用。
(3)使用公共属性
使用公共属性也是一种比较常用的方式,通过窗体设计器添加的控件默认访问修饰符为private级别,可以设置成public或Internal(在程序集内部可见)来对外公开。
比如对窗体中的Button进行公开,那就可以访问Button的相关属性,同时也可以注册事件或撤销事件注册。
如,
form.buttonOK.Click+=newEventHandler(buttonOK_Click);
form.ShowDialog();
对于只允许读取访问或修改访问的控件或变量可以通过属性来控制。
对
(1)方式进行修改,去除重载构造函数,增加属性也可以实现同样的效果。
publicobjectMyParams
get{returnthis.myParams;
set{this.myParams=value;
(4)使用公共方法
使用公共方法类似于属性,对上面的同等实现如下,
//获取参数
publicobjectGetParams()
returnthis.myParams;
//设置参数
publicvoidSetParams(objectmyParams)
this.myParams=myParams;
(5)使用静态类该方式可以简单的理解为静态变量全局共享,通过下面代码能够比较清楚的理解,先来定义静态类,
publicstaticclassParameterSettings
//公共静态变量
publicstaticstringUsername="
Zhengzuo"
;
//私有静态变量
privatestaticstringuserRole="
Administrators"
privatestaticstringpassword="
//内部属性
internalstaticstringUserRole
get{returnuserRole;
//公共属性
publicstaticstringPassword
get{returnpassword;
privateset{password=value;
在需要访问的地方通过以下方式进行,
stringusername=ParameterSettings.Username;
stringpassword=ParameterSettings.Password;
stringuserRole=ParameterSettings.UserRole;
ParameterSettings.Username="
郑佐"
//修改成新用户名
(6)窗体实现Singleton模式
Singleton模式是我们开发过程中最常用的模式之一。
在技术社区经常看到有人谈及对主窗体实现Singleton,但个人认为这不是一种妥当的做法,因为没有这个必要。
这里通过另一个自定义类来进行演示。
假设UserLoginInfo类用来保存登录系统后的用户凭据。
/*==============================================
程序郑佐2006-4-23
==============================================*/
publicclassUserLoginInfo
//实现Singleton模式,线程安全。
privatereadonlystaticUserLoginInfocurrentUserInfo=newUserLoginInfo();
//提供全局访问点
publicstaticUserLoginInfoCurrentUserInfo
get{returncurrentUserInfo;
//阻止显式实例化,但不能阻止反射方式调用。
privateUserLoginInfo()
//公共变量
publicstringUsername;
//私有变量
privatestaticstringuserRole;
privatestaticstringpassword;
internalstringUserRole
set{userRole=value;
publicstringPassword
internalset{password=value;
在其他代码中进行访问,
UserLoginInfo.CurrentUserInfo.Username="
UserLoginInfo.CurrentUserInfo.UserRole="
dotnetlover"
UserLoginInfo.CurrentUserInfo.Password="
对于Singleton模式的实现方式有很多,编写时需要考虑是否需要保证实例访问的线程安全问题,以免引发不可预料的情况,为了提高性能可以考虑惰性实例化。
关于Singleton模式的更多信息可以参考另一篇文章。
(7)发布事件进行订阅
通过事件来传递参数应该说是一种推的实现方式,在产生事件时进行被动的获取相关数据。
这里将通过一个自定义事件来演示数据的传输。
在自定义事件时,标准的做法都会先定义一个事件参数类,要么直接使用基类EventArgs,或者从EventArgs继承实现自己的参数类,假设自定义基类取名为OptionSettingEventArgs,
//选项设置事件参数类
publicclassOptionSettingEventArgs:
EventArgs
privatestringchangedPath;
//构造函数
publicOptionSettingEventArgs(stringchangedPath)
this.changedPath=changedPath;
//读取参数
publicstringChangedPath
get{returnthis.chan