AlfaWizard 库






4.61/5 (14投票s)
AlfaWizard 是一个简单的库,用于创建向导。

引言
AlfaWizard
库是一个简单的库,用于创建向导。该库允许通过几行源代码和一个特殊的*.xml配置文件来创建完整的向导。此 XML 文件有助于减少源代码行数,因为它设置了各个页面的属性。页面的属性也可以从程序中设置。整个向导的基础元素是主窗口,其中各个页面可以根据用户操作进行更改。用户无法直接访问主向导窗口,但可以通过主向导类WizardDialog
更改属性。
背景
向导的行为可以与有限状态机(FSM)进行比较。每个页面都代表自动机中的一个状态。我们在输入(用户输入)的帮助下在各个状态之间移动。每个页面(FSM 的状态)都有一个可以从外部看到的输入值。由于 FSM 和简单的向导非常相似,我决定用最接近 FSM 的行为来实现我的库。因此,可以根据用户输入选择向导页面。

Using the Code
在创建AlfaWizard
库时,我的目的是减少用户必须编写的源代码行数。通过使用 XML 配置文件实现了这一点。BasePage
使用各种 XML 元素,向导中使用的所有页面都必须从此派生。在附带的测试项目中,在TestClass
类中,您可以看到用户只需很少的行数即可创建一个好的向导。该库还包含一组异常,可以帮助调试应用程序。
名称 | 描述 |
BaseException |
所有其他AlfaWizard 异常都从此基本异常BaseException 派生。此异常没有附加数据。 |
InitException |
在页面初始化过程中引发。 |
PageInsertException |
当您尝试将未初始化的页面插入WizardDialog 时,将引发此异常。 |
ParseException |
读取 XML 配置文件时引发任何异常时,将引发此异常。 |
PageNotFoundException |
当您尝试使用WizardDialog 中不存在的页面时,将引发此异常。 |
在测试项目中,您还可以找到如何派生自己的页面并在向导中使用它。向导已提供的页面是线程安全的。在页面之间传输数据的情况下,我使用了一些接口,如IDirBrowse
或ILicenseAccept
。例如,要在ProgressPage
中获取解压缩 zip 文件的路径,我们这样做:
//automatically jumps to next page if it’s a 100% on progress bar
progress.AutoJumpNext = true;
//id of the page that must implement IDirBrowse,
//from which you get a path where zip archive is unzipped
progress.BrowsePageId = browse.Information.Id;
//operation that starts in separate thread after the page is shown
progress.ProgDeleg = WorkingTest;
示例 TestClass
public class TestClass
{
private readonly string dirPath;
private WizardDialog wd;
private IntroPage intro;
private LicensePage license;
private FinalPage final;
private TestPage test;
private AlfaPage alfa;
private BetaPage beta;
public TestClass ()
{
dirPath = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
//create object WizardDialog, where 2nd argument in constructor is language
wd = new WizardDialog(Path.Combine(dirPath, "configFile.xml"), "en");
//create object intro page, 1st argument is object type of WizardDialog,
//2nd is page name in XML file, 3rd is allowed wizard buttons
intro = new IntroPage(wd, "My Intro Page", WindowButtons.NextCancel);
license = new LicensePage(wd, "My license page", WindowButtons.BackNextCancel);
test = new TestPage(wd, "My own test page", WindowButtons.BackNextCancel);
final = new FinalPage(wd, "Designer final page", WindowButtons.BackNextCancel);
alfa = new AlfaPage(wd, "AlfaPage", WindowButtons.BackNextCancel);
beta = new BetaPage(wd, "BetaPage", WindowButtons.BackNextCancel);
//now we specify previous and next page for intro page
intro.Initialize(null, license);
license.Initialize(intro, test);
PageInformationCollection testBack = new PageInformationCollection();
testBack.Add(license.Information);
PageInformationCollection testNext = new PageInformationCollection();
testNext.Add(alfa.Information);
testNext.Add(beta.Information);
//now we specify one previous page and two next pages for test page
test.Initialize(testBack, testNext);
alfa.Initialize(test, final);
beta.Initialize(test, final);
final.Initialize(test, null);
//after page initialization you must insert page
//into WizardDialog.Pages collection
wd.PageAdd(intro);
wd.PageAdd(final);
wd.PageAdd(license);
wd.PageAdd(test);
wd.PageAdd(alfa);
wd.PageAdd(beta);
}
public void Run()
{
//now we show wizard
wd.ShowWizard();
}
}
如何创建自己的页面
如果您想为没有附加功能的向导创建自己的页面,只需创建一个新控件并将此代码添加到其中即可。
public partial class AlfaPage : BasePage
//control inherit from BasePage
{
//this constructor is mandatory
public AlfaPage()
{
InitializeComponent();
}
//this constructor is mandatory
public AlfaPage(WizardDialog wd) : base (wd)
{
InitializeComponent();
}
//this constructor is mandatory
public AlfaPage(WizardDialog wd, string name) : base(wd, name)
{
InitializeComponent();
}
//this constructor is mandatory
public AlfaPage(WizardDialog wd, string name, WindowButtons dialogButtons)
: base(wd, name, dialogButtons)
{
InitializeComponent();
}
}
此处描述了BasePage
类中所有重要的方法。如果您想覆盖某些方法,必须始终先调用基类方法。基类方法会调用可以处理并由向导响应的事件。
方法名称(所有方法均为公共,参数已省略) | 描述 |
bool Initialize |
这是由页面初始化调用的方法,其中指定了前驱和后继。在此方法中,页面设置从配置文件读取。 |
PageInformation RunBack |
当用户单击“后退”按钮时,调用此方法。 |
PageInformation RunNext |
当用户单击“下一步”按钮时,调用此方法。 |
bool WorkBeforeShow |
在页面显示在向导窗口中之前调用此方法。 |
bool WorkAfterShow |
在页面显示在向导窗口中之后调用此方法。 |
bool WorkBeforeBack |
在用前一页替换当前页之前调用此方法。 |
bool WorkBeforeNext |
在用下一页替换当前页之前调用此方法。 |
bool WorkCancel |
当用户关闭向导窗口时调用此方法。调用此方法以级联向导的所有前一页。 |
string ToString |
如果要使用WizardLogger 类,请不要覆盖此方法。 |
XML 配置文件示例
包含的示例包含一个配置文件,用于设置各个向导页面的属性。文件名为configFile.xml,其基本结构如下:
<?xml version="1.0" encoding="utf-8" ?>
<Wizard>
<WizardDialog>
<Language type="en">
<BackButtonName>Back</BackButtonName>
<NextButtonName>Next</NextButtonName>
<FinishButtonName>Finish</FinishButtonName>
<CancelButtonName>Cancel</CancelButtonName>
<CancelWizardMsg>Do you want cancel this dialog?</CancelWizardMsg>
<WizardHeaderMsg>Warning</WizardHeaderMsg>
</Language>
</WizardDialog>
<IntroPage name="My Intro Page">
<Language type="en">
<Purpose>This is purpose of dialog</Purpose>
<WindowTitle>Window title 1</WindowTitle>
<ActionName>Action name 1</ActionName>
<ActionDescription>Action description 1</ActionDescription>
<HeaderImagePath></HeaderImagePath>
</Language>
</IntroPage>
<LicensePage name="My license page">
<Language type="en">
<WindowTitle>Window title 2</WindowTitle>
<ActionName>Action name 2</ActionName>
<ActionDescription>Action description 2</ActionDescription>
<HeaderImagePath></HeaderImagePath>
<LicenseText>test</LicenseText>
<!--<LicenseText type="rtf">paste rtf document here</LicenseText>-->
<Accept>I agree license agreement</Accept>
<Refuse>I not accept license agreement</Refuse>
<NotValidText>You must accept license agreement
before continue!</NotValidText>
</Language>
</LicensePage>
<FinalPage name="Designer final page">
<Language type="en">
<WindowTitle>Window title 4</WindowTitle>
<ActionName>Action name 4</ActionName>
<ActionDescription>Action description 4</ActionDescription>
<HeaderImagePath></HeaderImagePath>
</Language>
</FinalPage>
<TestPage name="My own test page">
<Language type="en">
<WindowTitle>Window title 3</WindowTitle>
<ActionName>Action name 3</ActionName>
<ActionDescription>Action description 3</ActionDescription>
<HeaderImagePath></HeaderImagePath>
</Language>
</TestPage>
</Wizard>
未来发展
考虑到用户无法访问主应用程序窗口,我计划将来将主窗口的所有元素属性都引入WizardDialog
类以及配置文件中。
历史
- 2008年8月21日 - 文章初版
- 2008年8月30日 - 新库版本 (0.0.1.0),请参阅变更日志
更改日志
- 版本 0.0.0.1 发布于 2008 年 8 月 21 日
- 库的第一个正式版本
- 版本 0.0.1.0 发布于 2008 年 8 月 30 日
- 将方法
WizardDialog.RunBack()
和WizardDialog.RunNext()
的返回类型更改为void
新的只读属性
PreviousPage
,有助于获取返回页面,尤其是在(从状态 6 返回到状态 4 或 5)时- 新的
WizardDialog
构造函数,WizardDialog(Stream xmlStream, string language)
- 移除方法
ReadFromFile(string path, string xpath)
新的方法
ReadFromXml(Stream xmlStream, string xpath)
,取代旧方法ReadFromFile
特别感谢
我想感谢所有帮助我完成这篇文章的人。首先,感谢 Ing. Ondrej Plocica 提供理论帮助和建议。其次,感谢 Ing. Peter Gregan 帮助我进行翻译。