Winform multiple Usercontrols for different page under one Form
我正在尝试使用 Winform 构建一个应用程序 UI,其中将包含多个页面。假设软件将在启动时要求登录凭据,然后登陆仪表板。然后用户将可以选择转到不同的页面,例如:Page1 - Page2 - Page3。
现在我计划制作一个表单,所有这些页面都将是单独的用户控件。因此,根据要求,我将更改这些用户控件的可见性。
现在要做到这一点,我将下面的代码放入 Form1.cs
1 2 3
| ControlLogin ucLogin = new ControlLogin ();
ucLogin .Location = new System.Drawing.Point(12, 67);
this.Controls.Add(ucLogin ); |
这很好用。但是,在从此 ControlLogin.cs 打开任何 UserControl 时,我将如何将新的 UserControl(比如 Page1Control)添加到 Form1 的列表中?
- RAD 方法是使用不带标签的 TabControl。
-
您只需要在用户控件中引用表单即可。以一种简单、通用的方式,您已经使用 button_loadStuff_Click(..){Form myParent = this.Parent; NextPage nextPage = new NextPage(); myParent .Controls.Add(nextPage);} 作为更强大的 ref,您需要将其声明为真正的 from 类型,默认情况下称为 Form1。有了这个,您还可以访问表单中的所有(公共)字段。
你选择的基本布局对我来说很好。
您的实际问题似乎是:如何从这些 UC 中引用表单?
这与以下问题密切相关:如何从其他表单中引用一个表单或其中的一部分?这里经常被问到这个问题..
这是我建议你应该做的:
创建一个公共函数来打开你的每个 UCs openLogin, openPageOne..
更改每个 UC 的构造函数以包含一个 Form1 作为参数(假设您的表单具有默认名称)并相应地调用它,如下所示: ControlLogin ucLogin = new ControlLogin(this);
在 UC 构造函数中,您希望将传入的表单存储在类变量中。
以你写的形式:
1 2 3 4 5 6 7 8 9 10 11 12
| public void openLogin (Form1 f )
{
ControlLogin ucLogin = new ControlLogin (this);
ucLogin .Location = new System.Drawing.Point(12, 67);
this.Controls.Add(ucLogin );
}
public void openPageOne (Form1 f )
{
..
} |
在 UC 中:
1 2 3 4 5 6 7
| public ControlLogin(Form1 form1)
{
InitializeComponent();
mainForm = form1;
}
Form1 mainForm = null; |
现在你可以在表单中引用所有的公共字段和方法了,可能是这样的
1
| if (logingIsOK) mainForm.openPageOne(); |
-
感谢分享。这就是我一直在寻找的。现在除此之外,您能否再指导我一些……也就是说,我正计划实现一些像这样的分组机制……每个组可以有多个页面(UC)。一旦一个组进入视野,所有其他组都应该是不可见的。这样我就可以实现PageOne、PageTwo下的内页。我可以将这些控件添加到多个数组(组)的列表中并循环遍历它们以更改可见性吗?
-
是的,是的。将它们放在列表中可能是一个好主意。然后你可以在显示新的之前隐藏所有的 openXXX 功能。但是您需要对此做出决定:您想将它们全部保留吗?如果很好,如果不是,您将不得不处理它们。这实际上取决于它们包含的内容。也许您想要免费或保持开放的 DB 连接?你决定!一个人甚至可能想预先创建所有内容-但这又取决于:一开始会放慢速度还是会感觉更快..-另外:您是否想在页面之间来回移动...?...
-
.. 但是 List<ucBaseClass> myPages 肯定是一个好主意,也是一个 ucBaseClass currentPage 变量..
-
好。页面之间的循环将在那里。但是每次打开页面时,它都会显示它的初始阶段,即所有具有空白值的字段。显示我认为显示/隐藏对我来说很好。是的,如果那里出现一些数据库连接问题,我将不得不考虑处理。
-
好的,但请记住,显示/隐藏不会重置任何字段。因此,要么去删除并在必要时处理 uc,要么编写一个重置函数,这样你就可以重置 soem 并保留其他值。还要注意"处理"和"删除"之间的区别。您只需要处理 IDisposable 的东西!流是一个例子,大多数像位图这样的 GDI 东西是另一个例子。另外请注意,处理本身不会递归地工作!您将需要自己遍历所有嵌套的 IDisposables。因此,对于 List<Bitmap>,您需要将它们全部枚举出来。
您需要为您的页面开发一些事务逻辑。我建议在您的主窗体上使用面板作为容器。在此容器中,您将放置当前用户控件,即用户选择的控件。
例如:
1 2 3 4 5 6 7 8 9
| internal void ReplaceUserPage(Control container, UserControl userRequest)
{
if (container.Controls.Count == 1)
{
container.Controls.RemoveAt(0);
}
container.Controls.Add(userRequest);
userRequest.Dock = DockStyle.Fill;
} |
如果您没有动态页面,则可以将它们全部设为单例。这样,每个实例都将按需创建并存在于内存中,随时可以重用。因此,当用户单击菜单或按钮打开页面时,您可以执行
1 2
| UserControl requested = Page1Control.GetInstance();
ReplaceUserPage(container, requested); |
使用单例,您甚至不需要保留控件列表。我并不是说这是最好的、完美的或一刀切的方式。有许多控制事务方法。这取决于系统复杂性和其他因素。
- 我理解你的单身概念,我最初的计划也是这样做的。让我今晚更深入地了解这个项目。之后会回来评论。感谢分享。