使用 C# 创建向导布局






3.42/5 (9投票s)
一篇关于使用 C# Windows Forms 应用程序创建向导布局的文章。
引言
我们可能见过很多我们遇到的向导,带有“上一步”、“下一步”、“取消”按钮。如果为向导的每个步骤设计单独的窗体,并在每个窗体上复制一组按钮,这会很繁琐。因此,我决定创建一个基本模板(父窗体),该模板可以根据用户单击“上一步”或“下一步”按钮来加载(向导步骤的)窗体。该布局的一个额外优点是,根据加载的窗体,“上一步”和“下一步”按钮会自动禁用。
使用代码
我将向您介绍一些我将用来更改窗体的变量。
变量 | 目的 |
---|---|
int top |
当前使用的窗体的索引。 |
int count |
我们将要在向导中使用的窗体的总数。 |
Form[] frm |
向导中使用的窗体的数组集合 |
让我们假设一个堆栈的情况。堆栈有一个 top
变量,它对应于堆栈的当前元素。top
变量会根据事件不断变化。(即)对于下一个元素(下一步)会增加,对于上一个元素(上一步)会减少。
我们假设堆栈的值 top = -1
表示没有更多可以后退的窗体(下溢条件)。如果 top = count
,则表示没有更多可以前进的窗体(上溢条件)。我们将实现相同的概念,但我们将处理窗体。
请按照以下步骤操作,
设计父窗体
- 创建一个新的 Windows 窗体项目。
- 添加一个窗体。将其命名为
frmParent
。这将是我们的父(宿主)窗体。 - 根据您的内容向窗体添加三个面板,并将它们命名为
pnlLeft
、pnlContent
、pnlNavigation
,并将其停靠属性分别设置为Left
、Fill
、Bottom
。 - 我们将使用
pnlLeft
显示徽标,使用pnlContent
更改窗体,并使用pnlNavigation
进行导航按钮。
现在,父窗体的布局应该如下所示:
- 使用适当的控件设计窗体的基本布局。我使用了一个 PictureBox 来显示向导的徽标。我在
pnlNavigation
中添加了一个TableLayoutPanel
,它包含三个按钮(即“上一步”、“下一步”和“取消”)。 - 添加按钮,并为它们命名为
btnBack
、btnNext
、btnCancel
。 - 我添加了必要的内边距以获得外观和感觉。您可以根据您的布局设计尝试一下。
输出应类似于:
设计子窗体
您可以在向导中创建任意数量的子窗体。但请确保您设计的每个子窗体都具有以下属性:
属性 | 值 |
---|---|
FormBorderStyle | 无 |
AutoScroll |
True |
根据您的要求设计子窗体,从起始窗体到结束窗体。本次演示,我设计了三个窗体,即 frm1
、frm2
、frm3
。在这种情况下,frm1
将作为第一个窗体,frm3
将作为最后一个窗体。
我在附件中提供了一个第一个窗体(frm1
)的示例。已将 FormBorderStyle 设置为 none,并将 AutoScroll 属性打开。我还应用了必要的内边距,并调整了其他属性以获得窗体的外观。
编码
最初,我需要初始化 Form
数组,其中包含我将在向导中使用的窗体。代码必须放在父窗体的构造函数之前。
Form[] frm = { new frm1(), new frm2(), new frm3() };
int top = -1;
int count;
现在,在父窗体的构造函数中,我们需要初始化 count
变量。
public frmParent()
{
count = frm.Count();
InitializeComponent();
}
我创建了一个函数,用于将当前设置的窗体加载到主窗体的面板(pnlContent
)中。我将其命名为 LoadNewForm()
。此函数将被调用三次:
- 在父窗体加载期间(第一次,必须显示第一个窗体)
- 在单击“上一步”按钮期间(必须加载上一个窗体)
- 在单击“下一步”按钮期间(必须加载下一个窗体)。
它看起来应该类似这样:
frm[top].TopLevel = false;
frm[top].Dock = DockStyle.Fill;
this.pnlContent.Controls.Clear();
this.pnlContent.Controls.Add(frm[top]);
frm[top].Show();
该函数使子窗体充当子窗体(使用 TopLevel
属性),将窗体作为内容填充到父窗体的面板中(使用 DockStyle.Fill
),清除面板中的所有内容以重新加载窗体(pnlContent.Controls.Clear()
),将当前窗体(top
)添加到面板中,并在面板中显示该窗体。
要理解这段代码,您可以参考 Codeproject 上发布的这个问题:https://codeproject.org.cn/Questions/414107/Csharp-Form-inside-a-Panel
移至下一个窗体
如果单击“下一步”按钮,则必须发生以下情况:
top
变量必须增加。- 如果
top
的值超过或等于窗体的总数,则什么也不做(return
)。 - 否则,将当前窗体加载到面板中,并检查当前窗体是否是列表中的最后一个窗体。如果是,则禁用“下一步”按钮。
- 如果没有更多可用窗体(即
top == -1
),则禁用“上一步”按钮。
代码应如下所示:
private void Next()
{
top++;
if (top >= count)
{
return;
}
else
{
btnBack.Enabled = true;
btnNext.Enabled = true;
LoadNewForm();
if (top + 1 == count)
{
btnNext.Enabled = false;
}
}
if (top <= 0)
{
btnBack.Enabled = false;
}
}
在 Form Load
期间以及在单击 next button
时调用 Next()
。
移至上一个窗体
移至上一个窗体与移至下一个窗体完全相反。因此,代码如下:
private void Back()
{
top--;
if (top <= -1)
{
return;
}
else
{
btnBack.Enabled = true;
btnNext.Enabled = true;
LoadNewForm();
if (top - 1 <= -1)
{
btnBack.Enabled = false;
}
}
if (top >= count)
{
btnNext.Enabled = false;
}
}
在单击 back button
时调用 Back()
。
就是这样。就是全部代码,代码看起来如下:
public partial class frmParent : Form
{
Form[] frm = { new frm1(), new frm2(), new frm3(), new frm4(),
new frm5()};
int top = -1;
int count = 5;
public frmParent()
{
InitializeComponent();
}
private void LoadForm()
{
frm[top].TopLevel = false;
frm[top].AutoScroll = true;
frm[top].Dock = DockStyle.Fill;
this.pnlContent.Controls.Clear();
this.pnlContent.Controls.Add(frm[top]);
frm[top].Show();
}
private void Back()
{
top--;
if(top <= -1)
{
return;
}
else
{
btnBack.Enabled = true;
btnNext.Enabled = true;
LoadForm();
if (top - 1 <= -1)
{
btnBack.Enabled = false;
}
}
if(top>=count)
{
btnNext.Enabled = false;
}
}
private void Next()
{
top++;
if (top >= count)
{
return;
}
else
{
btnBack.Enabled = true;
btnNext.Enabled = true;
LoadForm();
if(top+1 == count)
{
btnNext.Enabled = false;
}
}
if (top <= 0)
{
btnBack.Enabled = false;
}
}
private void frmParent_Load(object sender, EventArgs e)
{
Next();
}
private void btnNext_Click(object sender, EventArgs e)
{
Next();
}
private void btnBack_Click(object sender, EventArgs e)
{
Back();
}
}
我为某些组件应用了停靠。因此,即使您调整应用程序的大小或最大化它,它们也能适应。根据设计的风格,也可以将“取消”按钮重命名为“完成”按钮。
历史
版本 1:当前版本