问题描述
我有一个很大的winform,上面有6个标签,里面装有控件。第一个标签是主标签,其他5个标签是主标签的一部分。用数据库术语来说,其他5个选项卡都有对主选项卡的引用。
可以想象,我的表格越来越大且难以维护。所以我的问题是,您如何处理大型UI?你如何处理?
解决方法
开始之前请考虑您的目标。我认为您想以SOLID原则为目标。除其他外,这意味着班级/方法应负单一责任。就您而言,表单代码可能是协调UI内容和业务规则/域方法。
分解为用户控件是一个很好的开始。例如,在您的情况下,每个选项卡可能只有一个用户控件。然后,您可以使实际的表单代码非常简单,从而加载和填充用户控件。您应该具有这些用户控件可以发布/订阅的命令处理器实现,以启用视图间对话。
另外,研究UI设计模式。 M-V-C尽管在基于状态的桌面应用程序中难以实现,但它非常受欢迎且建立良好。这引起了M-V-P /被动视图和M-V-VM模式。我个人是去MVVM的,但是如果您不小心的话,最终在WinForms中实现时可能会构建很多“框架代码”,请保持简单。
同样,开始考虑\“ Tasks \”或\“ Actions \”,因此构建一个基于任务的UI,而不是创建/读取/更新/删除(CRUD)UI。认为绑定到第一个选项卡的对象是聚合根,并具有用户可以单击以执行某些任务的按钮/工具栏/链接标签。当他们这样做时,可以将他们导航到一个完全不同的页面,该页面仅聚合完成该工作所需的特定字段,因此消除了复杂性。
命令处理器
命令处理器模式基本上是用于用户启动的事件的同步发布者/消费者模式。下面是一个基本的(相当幼稚的)示例。
本质上,您要使用此模式来实现的是从表单本身移走事件的实际处理。表单可能仍会处理UI问题,例如隐藏/禁用控件,动画等,但是您的目标是将真正的业务逻辑完全分开。如果您拥有丰富的域模型,则“命令处理程序”将实质上协调对域模型上方法的调用。命令处理器本身为您提供了一个有用的地方,可以将处理程序方法包装在事务中,也可以提供AOP样式的内容,例如审计和日志记录。
public class UserForm : Form
{
private ICommandProcessor _commandProcessor;
public UserForm()
{
// Poor-man\'s IoC,try to avoid this by using an IoC container
_commandProcessor = new CommandProcessor();
}
private void saveUserButton_Click(object sender,EventArgs e)
{
_commandProcessor.Process(new SaveUserCommand(GetUserFromFormFields()));
}
}
public class CommandProcessor : ICommandProcessor
{
public void Process(object command)
{
ICommandHandler[] handlers = FindHandlers(command);
foreach (ICommandHandler handler in handlers)
{
handler.Handle(command);
}
}
}
, 处理大型UI的关键是关注点和封装的清晰分离。以我的经验,最好使UI尽可能不包含任何数据和功能:Model-View-Controller是一种著名的(但很难应用)模式来实现。
由于用户界面往往仅受用户界面代码的困扰,因此最好将所有其他代码与用户界面分离,并将与用户界面无关的所有事物直接委托给其他类(例如,将用户输入的处理委托给其他用户)。控制器类)。您可以通过为每个选项卡设置一个控制器类来应用此功能,但这取决于每个选项卡的复杂程度。也许最好将一个选项卡本身分解为几个控制器类,然后将它们组合在单个控制器类中以使该选项卡更容易处理。
我发现MVC模式的一种变体很有用:被动视图。在这种模式下,视图仅保留UI组件的层次结构和状态。其他所有内容都委托给控制器类并由其控制,该控制器类确定如何根据用户输入进行操作。
当然,这也有助于将UI本身分解为组织良好且经过封装的组件本身。
, 我建议您从Microsoft的实践和模式中阅读有关CAB(复合UI应用程序块)的信息,该功能具有以下模式:命令模式,策略模式,MVP模式...等。
Microsoft实践和模式
复合UI应用程序块