65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 创建向导布局

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.42/5 (9投票s)

2016 年 6 月 26 日

CPOL

5分钟阅读

viewsIcon

37091

downloadIcon

3249

一篇关于使用 C# Windows Forms 应用程序创建向导布局的文章。

引言

我们可能见过很多我们遇到的向导,带有“上一步”、“下一步”、“取消”按钮。如果为向导的每个步骤设计单独的窗体,并在每个窗体上复制一组按钮,这会很繁琐。因此,我决定创建一个基本模板(父窗体),该模板可以根据用户单击“上一步”或“下一步”按钮来加载(向导步骤的)窗体。该布局的一个额外优点是,根据加载的窗体,“上一步”和“下一步”按钮会自动禁用。

使用代码

我将向您介绍一些我将用来更改窗体的变量。

变量 目的
int top 当前使用的窗体的索引。
int count 我们将要在向导中使用的窗体的总数。
Form[] frm 向导中使用的窗体的数组集合

让我们假设一个堆栈的情况。堆栈有一个 top 变量,它对应于堆栈的当前元素。top 变量会根据事件不断变化。(即)对于下一个元素(下一步)会增加,对于上一个元素(上一步)会减少。

我们假设堆栈的值 top = -1 表示没有更多可以后退的窗体(下溢条件)。如果 top = count,则表示没有更多可以前进的窗体(上溢条件)。我们将实现相同的概念,但我们将处理窗体。

请按照以下步骤操作,

设计父窗体

  • 创建一个新的 Windows 窗体项目。
  • 添加一个窗体。将其命名为 frmParent。这将是我们的父(宿主)窗体。
  • 根据您的内容向窗体添加三个面板,并将它们命名为 pnlLeftpnlContentpnlNavigation,并将其停靠属性分别设置为 LeftFillBottom
  • 我们将使用 pnlLeft 显示徽标,使用 pnlContent 更改窗体,并使用 pnlNavigation 进行导航按钮。

现在,父窗体的布局应该如下所示:

  • 使用适当的控件设计窗体的基本布局。我使用了一个 PictureBox 来显示向导的徽标。我在 pnlNavigation 中添加了一个 TableLayoutPanel,它包含三个按钮(即“上一步”、“下一步”和“取消”)。
  • 添加按钮,并为它们命名为 btnBackbtnNextbtnCancel
  • 我添加了必要的内边距以获得外观和感觉。您可以根据您的布局设计尝试一下。

输出应类似于:

Sample Layout Design

设计子窗体

您可以在向导中创建任意数量的子窗体。但请确保您设计的每个子窗体都具有以下属性:

属性
FormBorderStyle
AutoScroll True
   

根据您的要求设计子窗体,从起始窗体到结束窗体。本次演示,我设计了三个窗体,即 frm1frm2frm3。在这种情况下,frm1 将作为第一个窗体,frm3 将作为最后一个窗体。

我在附件中提供了一个第一个窗体(frm1)的示例。已将 FormBorderStyle 设置为 none,并将 AutoScroll 属性打开。我还应用了必要的内边距,并调整了其他属性以获得窗体的外观。

Sample Child Form Design

编码

最初,我需要初始化 Form 数组,其中包含我将在向导中使用的窗体。代码必须放在父窗体的构造函数之前。

        Form[] frm = { new frm1(), new frm2(), new frm3() };
        int top = -1;
        int count;

现在,在父窗体的构造函数中,我们需要初始化 count 变量。

public frmParent()
        {
            count = frm.Count();
            InitializeComponent();
        }

我创建了一个函数,用于将当前设置的窗体加载到主窗体的面板(pnlContent)中。我将其命名为 LoadNewForm()。此函数将被调用三次:

  1. 在父窗体加载期间(第一次,必须显示第一个窗体)
  2. 在单击“上一步”按钮期间(必须加载上一个窗体)
  3. 在单击“下一步”按钮期间(必须加载下一个窗体)。

它看起来应该类似这样:

            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:当前版本

© . All rights reserved.