WinForms 的简单向导
一个简单的向导
更新:2018-05-17
本文最初发表于 8 年前。 后来 CodePlex 停止了服务。 因此,我已将代码移至 GitHub,以便仍然觉得这有用的任何人都可以使用。 只需单击本文顶部的新的下载链接即可。
引言
正在寻找一种快速简便的方法来创建向导主机? 别再找了。 SimpleWizard 为您的向导页面、导航甚至基本主机提供了所需的接口。 主机需要做一些工作,因为它的 UI 相当简陋,但本文的主题实际上是如何处理导航等。 我将所有美化工作留给读者。
接口
public interface IWizardPage
{
UserControl Content { get; }
void Load();
void Save();
void Cancel();
bool IsBusy { get; }
bool PageValid { get; }
string ValidationMessage { get; }
}
这是基本要求:一个可以用于向导页面的接口。 只需创建一些用户控件(页面),继承 IWizardPage
,然后就可以进行该步骤了。
集合和导航
public enum WizardPageLocation
{
Start,
Middle,
End
}
public class WizardPageCollection : Dictionary<int, IWizardPage>
{
public IWizardPage CurrentPage { get; private set; }
public IWizardPage FirstPage { get; }
public IWizardPage LastPage { get; }
public WizardPageLocation PageLocation { get; private set; }
public bool CanMoveNext { get; }
public bool CanMovePrevious { get; }
public WizardPageCollection()
{
PageLocation = WizardPageLocation.Start;
}
public delegate void
WizardPageLocationChangedEventHanlder(WizardPageLocationChangedEventArgs e);
public event WizardPageLocationChangedEventHanlder WizardPageLocationChanged;
public IWizardPage MovePageFirst()
public IWizardPage MovePageLast()
public IWizardPage MovePageNext()
public IWizardPage MovePagePrevious()
public int IndexOf(IWizardPage wizardPage)
public void Reset()
private void NotifyPageChanged(int previousPageIndex)
}
public class WizardPageLocationChangedEventArgs
{
public WizardPageLocation PageLocation { get; set; }
public int PageIndex { get; set; }
public int PreviousPageIndex { get; set; }
}
您可以看到,我只提供了方法等的签名。这是为了清晰起见。 您可以在源代码中找到实际实现,网址为 http://simplewizard.codeplex.com/。
现在,为了更好地了解 MovePage...()
方法中发生的事情,请在此处查看 MovePageNext()
public IWizardPage MovePageNext()
{
int previousPageIndex = IndexOf(CurrentPage);
if (PageLocation != WizardPageLocation.End &&
CurrentPage != null)
{
// Find the index of the next page
int nextPageIndex = (from x in this
where x.Key > IndexOf(CurrentPage)
select x.Key).Min();
// Find the index of the last page
int lastPageIndex = (from x in this
select x.Key).Max();
// If the next page is the last page
if (nextPageIndex == lastPageIndex)
{
PageLocation = WizardPageLocation.End;
}
else { PageLocation = WizardPageLocation.Middle; }
// Set the current page to be the next page
CurrentPage = this[nextPageIndex];
NotifyPageChanged(previousPageIndex);
return CurrentPage;
}
return null;
}
您会注意到我们继承自 Dictionary<int, IWizardPage>
。 键是页码,值是 IWizardPage
。 简单地继承上述字典可以很好地为我们处理所有集合相关的事情。 现在,我们只需要关注导航即可。
有一些属性允许您直接访问集合中的当前页面、第一页和最后一页,以及一些属性,这些属性会告诉您是否可以向前移动,这些方法允许您实际在页面之间来回移动(如果可能)。 您唯一真正需要用到这个东西的地方是在您的主机窗体中,我们稍后会看到...
我想这样总结得很好。
向导主机
public partial class WizardHost : Form
{
private const string VALIDATION_MESSAGE = "Current page is not valid.
Please fill in required information";
public WizardPageCollection WizardPages { get; set; }
public bool ShowFirstButton { get; set; }
public bool ShowLastButton { get; set; }
public bool NavigationEnabled { get; set; }
public delegate void WizardCompletedEventHandler();
public event WizardCompletedEventHandler WizardCompleted;
public WizardHost()
{
InitializeComponent();
WizardPages = new WizardPageCollection();
WizardPages.WizardPageLocationChanged += new
WizardPageCollection.WizardPageLocationChangedEventHanlder
(WizardPages_WizardPageLocationChanged);
}
void WizardPages_WizardPageLocationChanged(WizardPageLocationChangedEventArgs e)
{
LoadNextPage(e.PageIndex, e.PreviousPageIndex, true);
}
private void NotifyWizardCompleted()
private void OnWizardCompleted()
public void UpdateNavigation()
private bool CheckPageIsValid()
public void LoadWizard()
public void LoadNextPage(int pageIndex, int previousPageIndex, bool savePreviousPage)
private void btnFirst_Click(object sender, EventArgs e)
private void btnPrevious_Click(object sender, EventArgs e)
private void btnNext_Click(object sender, EventArgs e)
private void btnLast_Click(object sender, EventArgs e)
}
这就是所有工作发生的地方。 在这里,您有 WizardPageCollection
,一些属性用于选择是否在向导上显示“第一页”和“最后一页”按钮(不显示“下一步”和“上一步”按钮是没有意义的,这就是为什么只有 2 个属性)。
所有导航更新都在这里进行,以及检查当前页面在移动到下一页之前是否有效。 CheckPageIsValid()
调用 IWizardPage
上的 PageValid
属性。 如果它返回 false
,则会显示一个消息框以及该页面的 ValidationMessage
属性。
同样,有关更多详细信息,请参阅源代码。
当您准备好启动向导时,您所需要做的就是添加您的向导页面,并将向导主机显示为对话框。 这是一个例子
private void button1_Click(object sender, EventArgs e)
{
WizardHost host = new WizardHost();
host.Text = "My Wizard";
host.WizardCompleted +=
new WizardHost.WizardCompletedEventHandler(host_WizardCompleted);
host.WizardPages.Add(1, new Page1());
host.WizardPages.Add(2, new Page2());
host.WizardPages.Add(3, new Page3());
host.LoadWizard();
host.ShowDialog();
}
结论
SimpleWizard
允许您忘记所有导航问题,只需将您的用户控件添加到 WizardHost
实例即可。 就这么简单。
历史
- 2010 年 10 月 26 日:初始发布