我是自学编程的人,并且没有接受任何正式的.NET编程培训。
前段时间,我开始使用C#开发GUI程序来控制传感器,项目蓬勃发展。我只是想知道如何在我的表单中最好地组织代码,特别是UI代码。
我的表格目前是乱七八糟的,或者至少对我来说是一团糟。
我的问题似乎是混乱,特别是国家财产,并且变得无法维护。此外,我的应用程序逻辑代码和UI代码在同一个文件中,在某种程度上,混合似乎是错误的,这意味着我需要做很多滚动才能找到我需要的东西。
如何构建.net表单?
由于
答案 0 :(得分:5)
有许多模式可以帮助您在应用程序中分离逻辑,从而使代码更清晰,更易于维护。 MVP模式是一个很好的开始。它基于定义3个响应区域,即MVP M =模型,V =视图,P =演示者。如果你熟悉使用接口你会没事的,否则这将是一个很好的起点(回顾基本的OO原则:封装,抽象,多态)。 MVP的基本原理是将应用程序逻辑放在Presenter中。 prenter通过一个接口与视图(你的表单)对话,当用户与它交互时,视图回调给演示者(我也使用这个接口)。该模型是解决方案的域对象层次结构,它包含商业逻辑和实体关系。
大多数UI模式(MVP,MCV等)都试图做同样的事情,分开你的担忧。以下是一个简单的例子:
//视图界面
interface IUserDetailsView
{
string Username{set;get;}
string FirstName{get;set;}
string LastName{get;set;}
UserDetailsPresenter Presenter{get;set;}
void DisplayMessage(string message);
}
//视图实施 //一个标准的窗体,有文本框,标签,组合等,
class UserDetailsView : Form, IUserDetails
{
public string Username{set{txtUserName.text = value;}get{return txtUserName.text;}}
public string FirstName{set{txtFirstName.text = value;}get{return txtFirstName.text;}}
public string LastName{set{txtLastName.text = value;}get{return txtLastName.text;}}
Public UserDetailsPresenter Presenter{get;set;}
public void DisplayMaessage(string message)
{
MessageBox.Show(message);
}
private void saveButton_Click(object sender, EventArgs e)
{
Presenter.SaveUserDetails();
}
}
//演示逻辑
class Presenter UserDetailsPresenter {
//Constructor
public userDetailsPresenter(IUserDetailsView view)
{
//Hold a reference to the view interface and set the view's presnter
_view = view;
_view.Presenter = this;
}
private IUserDetailsView _view;
DisplayUser(string userName)
{
//Get the user from some service ...
UserDetails details = service.GetUser(userName);
//Display the data vioa the interface
_view.UserName = details.UserName;
_view.FirstName = details.FirstName;
_view.LastName = details.LastName;
}
public void SaveUserDetails()
{
//Get the user dryaiols from the view (i.e. the screen
UserDetails details = new UserDetails();
details.UserName = _view.UserName;
details.FirstName = _view.FirstName;
details.LastName = _view.LastName;
//Apply some business logic here (via the model)
if(!details.IsValidUserDetails())
{
_view.DisplayMessage("Some detail outlining the issues");
return;
}
//Call out to some service to save the data
service.UpdateUser(details);
}
}
//最后,模型
public class UserDetails
{
public UserName {get;set;}
public FirstName{get;set;}
public LastName{get;set;}
public bool IsValidUserDetails()
{
if(LastName == "Smith")
{
//We do not allow smiths, remember what happened last time ... or whatever
return false;
}
return true;
}
}
希望这能解释责任是如何分离的。除了显示/格式化之外,表单没有逻辑,它也可以被删除以进行测试。演示者是视图和模型之间的中介,并调用服务,模型包含您的业务逻辑。正如已经提出的那样,这种模式存在差异,这可以使您的代码更轻薄,更灵活,但这概述了基本原则。我希望这会有所帮助。
: - )
答案 1 :(得分:2)
对于复杂的表单,我通常将代码拆分为单独的文件。你可以使用“partial class”来做到这一点。每个源代码文件都基于表单命名。例如,MainForm.cs,MainForm.State.cs,MainForm.Update.cs,MainForm.Menu.cs等。如果我有许多复杂的表单,我将为每个表单创建一个子文件夹。这里的一个提示是创建一个MainForm.Wip.cs表单。此部分类表单是您当前正在处理的代码。完成此代码后,您可以重命名代码或将代码移动到其他源代码文件。
此外,我还将创建用户控件。这具有代码重用的好处,并且它将许多功能移出表单。在http://msdn.microsoft.com/en-us/library/6hws6h2t.aspx查看“使用.NET Framework开发自定义Windows窗体控件”。
在http://www.codinghorror.com/blog/2007/12/nobody-cares-what-your-code-looks-like.html查看没有人关心你的代码是什么样的。在“组织”之前要考虑的事情。
答案 2 :(得分:1)
查看Model-View-Presenter模式:http://en.wikipedia.org/wiki/Model_View_Presenter
使用此模式,表单的代码隐藏应该主要包含对演示者的简单级联调用,这反过来将改变模型,将事件级联回视图(有时通过演示者,取决于您的实现)。 / p>
指出:您的表单(视图)不应包含任何状态信息;这将在演示者中,并且它不应该关心从何处获取数据,只要数据符合指定的合同即可。这样可以提高可测试性,因为您可以轻松地在演示者上测试状态和数据,并将视图分离,从而允许PLAF,相同数据的不同呈现以及相似的数据。
祝你好运:)答案 3 :(得分:1)
一些快速建议:
尝试将所有非UI代码移出表单,如果可能,您只希望以实际形式使用GUI代码。如果一个属性有副作用,它应该是一个函数。你的State属性几乎肯定是一个方法,看看你是否可以将代码分解为单独的方法,因此它只是每个状态的一个函数调用。
答案 4 :(得分:0)
这是一个经常使用的架构模式的链接。
http://en.wikipedia.org/wiki/Model_View_ViewModel
我也会查找其他一些架构模式,并对此进行更多研究,查找一些示例代码等。
答案 5 :(得分:0)
您应首先分析您的代码,以划分什么是应用程序逻辑和什么是UI逻辑。这些都不应该在同一个文件中。你的状态绝对绝不是UI逻辑,所以首先将它移出你的形式。这有助于您清除表单代码。
其次,阅读一些设计模式和原则。您可以找到一些很好的例子here,在您的情况下,我会查看行为模式,更具体地说是State和Mediator模式。它们不是解决问题的银子弹,但它可以让您更好地了解如何拆分应用程序和UI逻辑。
答案 6 :(得分:0)
我倾向于在usercontrols或自定义控件中添加尽可能多的代码。组件更易于重用,表单代码更易于阅读。
Usercontrols还可以处理和公开事件,使动态部件更容易与表单代码分离。
您甚至可以像在计时器上那样在表单上看不到自定义控件。
答案 7 :(得分:0)
我使用区域,如下:
#Region "_Edit"
Private Sub _edit_VisibleChanged(...) Handles _edit.VisibleChanged
End Sub
#End Region
从上到下,我的表单代码有:
听起来你的State属性需要被拆分,或者可能将代码移到其他类或例程中,因此复杂性更加隐藏。