返回首页

问题陈述
许多Windows Mobile应用程序使用一个选项或设置对话框来管理应用程序级别设置。对话框通常包含一个选项卡控件,如标签的每个标签上经常与一个或多个控制,复选框,单选按钮,下拉列表,updowns,文本框等下面的截图显示了一些例子。
{S0} {S1}
{S2} {S3}
当设计这样一个对话框,我们需要仔细考虑使用什么样的控制,有多少人在每个标签上的控制,以及如何布局的控制,让他们看看在不同的屏幕分辨率,大小和方向,可运营(纵向和横向)。如果我们要弹出一个软键盘来收集用户输入的布局问题变得更棘手。处理与布局问题的方法之一是设计为最小公分母 - 最低分辨率和最小的屏幕尺寸。但往往有时我们在每个标签上使用更多的标签和较少的控制,浪费宝贵的屏幕房地产,如果用户恰好有一个更高的分辨率和/或更大的屏幕尺寸的设备。 480X800的WVGA设备从下面的截图证明这一点。
{四至} {五}
应用程序设置"选项"对话框管理需要持久化数据存储。在全Net框架,这通常是一个设置文件,它对应的LT; userSettingsgt; app.config文件中的部分。在设计时设置文件是用来生成一个Settings类(从System.Configuration.ApplicationSettingsBase派生),它提供了每个设置的强类型访问器和设置保存到用户特定的文件(user.config)的能力。不幸的是,设置文件的机制不存在。NET Framework精简。我们都可以存储在注册表中的设置,这是容易部署和安全问题,或制定我们自己的方式来存储设置,在没有肖恩 - 米勒。双方雇一个XML文件,类似于LT; appSettingsgt; app.config文件中的部分。他们对待的应用程序设置"键 - 值对; flatquot没有如何设置可以组织结构支持。TreeView的组件基础的备选方案
在这篇文章中,我建议使用TreeView控件加上一个XML文件来管理应用程序设置。下面的屏幕截图显示了行动的组成部分。
{S6} {七}
{S8} {S9}
{S10}
从UI的角度来看,在TreeView组件基础的备选方案,具有以下优点:没有更多的布局头痛。它运作良好,无论我们有多少个选项,而我们使用的屏幕分辨率,大小和方向。选项​​可以组织团体,亚群,等直观和友好操纵杆(使用户可以单手操作)。向上和向下移动操纵杆上下移动选择光标(灰色)。移动操纵杆,有权展开节点。移动操纵杆,左边的折叠节点。当当前节点是一个价值节点,按导航键以选择它。当当前节点是一个折叠的组或选项节点,按操纵杆,将其展开。当当前节点是扩大集团或选项节点,按操纵杆,将其折叠。突出显示选定的值(黄色)。 有效利用屏幕面积。无需通过不同的选项卡或屏幕翻转,只是为了找到正确的选择。一致的所有选项的选择题式的操作。用户无需学习不同的,有时混淆的用户界面。
使用组件的唯一要求是,每个选项或设置必须从离散值,或像选择题选择一个值。这是不是太限制。 UI控件如单选按钮,下拉列表,updowns和复选框,实际上,选择题的控制类型。一个文本框,这是通常使用距离,如连续值选项,重量,高速缓存的大小等,应尽量避免不惜任何代价,因为它是这样的移动设备的麻烦,输入到一个文本框。因此,处理连续值选项时,我们应该思考的一种方式,而不是离散。能否描述的代表值设置合理,在我们的移动应用程序的特定背景下?是否有可能打破它分解成几个范围,例如,?我们所有的离散化的一个额外的好处:我们不需要任何输入验​​证,因为所有的值都是精心挑选的和有效的。
用来填充TreeView中的数据存储在一个XML文件。特定的XML文件只有三个,除了根节点的节点类型:组,期权和价值。的XML文件的一个例子如下:

<?xml version="1.0" encoding="utf-8" ?>

<options>

  <group name="General">

    <option name="TimeZone" displayName="Time zone">

      <value name="EST" selected="true" />

      <value name="CST" selected="false" />

      <value name="MST" selected="false" />

      <value name="PST" selected="false" />

    </option>

    <option name="UpdateInterval" displayName="Update interval">

      <value name="10" displayName="10 sec" selected="false" />

      <value name="30" displayName="30 sec" selected="true" />

      <value name="60" displayName="1 min" selected="false" />

      <value name="300" displayName="5 min" selected="false" />

      <value name="600" displayName="10 min" selected="false" />

    </option>

    <option name="CacheSize" displayName="Cache size">

      <value name="32" displayName="32 MB" selected="true" />

      <value name="64" displayName="64 MB" selected="false" />

      <value name="128" displayName="128 MB" selected="false" />

    </option>

    <option name="CheckInterval" displayName="Check for app update">

      <value name="0" displayName="Every time app starts" selected="true" />

      <value name="1" displayName="Every day" selected="false" />

      <value name="7" displayName="Every week" selected="false" />

      <value name="30" displayName="Every month" selected="false" />

      <value name="365" displayName="Every year" selected="false" />

    </option>

  </group>

  <group name="Appearance">

    <option name="Skin">

      <value name="Classic" selected="true" />

      <value name="IceFusion" displayName="Ice Fusion" selected="false" />

      <value name="Monochrome" selected="false" />

    </option>

    <option name="ShowToolbar" displayName="Show toolbar">

      <value name="true" selected="true" />

      <value name="false" selected="false" />

    </option>

    <option name="ShowStatusBar" displayName="Show status bar">

      <value name="true" selected="true" />

      <value name="false" selected="false" />

    </option>

  </group>

  <group name="SecurityPrivacy" displayName="Security &amp; Privacy">

    <option name="EnablePassword" displayName="Enable password protection">

      <value name="true" selected="true" />

      <value name="false" selected="false" />

    </option>

    <group name="SharedContents" displayName="Shared contents">

      <option name="ContactInfo" displayName="Contact info">

        <value name="true" selected="false" />

        <value name="false" selected="true" />

      </option>

      <option name="Photos">

        <value name="true" selected="true" />

        <value name="false" selected="false" />

      </option>

      <option name="Posts">

        <value name="true" selected="true" />

        <value name="false" selected="false" />

      </option>

    </group>  



  </group>

</options>

有这个XML的一些规则。每个节点类型有一个名称和一个DisplayName的属性。的名字,这是必需的,是在我们的程序中使用或引用。显示名称,这是可选的,用于在提交的TreeView。如果缺少DisplayName是,用于显示相应的名称。组可以包含零个或多个选项节点和组节点(或子)。我们可以作为嵌入式组节点的多层次,因为我们希望。选项​​必须只包含一个或多个值节点。只有一个选项的多个值节点之一可以有选择的属性的quot; truequot;,表明它是选项的当前值。
从编程的角度来看,使用这种XML作为数据存储我们的选项组件具有以下优点:两个XML和TreeView树结构的基础上。一个用于存储和提交。这种完美的匹配,使编程容易。组和子组组织本质上是支持的。它可以很容易地管理所选的价值观和所有可用的值。随着传统的设置文件,只有选定的值是持久性的,但同时中国又可用的值是在一个单独的资源文件,或硬编码在程序的。在一定程度上,我们可以改变的选项,而无需重新编译我们的程序。它也可以远程更新XML。它使本地化更容易。只要不同的语言翻译所有的displayName属性。实施
最大的灵活性,我并没有选项quot; componentquot;一个用户控件或类库。只需一个简单的类,您可以复制并粘贴到您的项目。{C}
关于代码的一些亮点:
首先我们需要通过XML文件,Options.xml,嵌入的资源,其建设行动属性在Visual Studio中设置为"嵌入的资源"。正如我们OptionsManager类的静态构造函数在第一次启动应用程序,所指出的,XML文件加载到内存从通过嵌入的LoadDefault方法资源,并保存到我们的应用程序可执行文件所在的位置。在随后的时间,因为XML文件中已经存在在我们的应用程序的根,我们只是从那里加载它。
LoadToTreeView方法加载XML文档到指定的TreeView控件。既然我们可以多层次的嵌入式组节点,我们需要做的递归加载,在私营的DoLoading方法表示。为一组节点,我们将展示其displayName在TreeView。对于一个选项节点,我们将展示其displayName和当前选定的值的DisplayName(分离":")。对于一个价值节点,我们将展示其displayName,如果它是当前选定的,我们也设置其背景颜色selectedValueBackColor。每个树节点,我们构建一个XPath相应的XML节点,并将它存储到树节点的Tag属性。后来,我们可以很容易地匹配这个XPath与XML节点的树节点。作为一个例子,如下表所示的XPath看起来像一个特定的树节点:
树节点的XPath一般/时区选项 /组[@名称='一般'] / [@名称='时区'] 一般/时区/太平洋标准值/组[@名称='一般'] / [@名称='时区'] /值[@名称='科普']
ChangeValue方法是所谓的,只要我们想改变的一个选项值。这通常是按下操纵杆时触发。我们需要做两件事情,在这个方法。首先,在TreeView控件中,我们需要更新相应的选项节点的显示和更改荧光笔成为当前选定的值的节点。其次,在底层的XML文档,我们需要更新相应的选项,以反映当前选定的价值的价值节点的选定属性。
GetOptionValue方法返回选定的选项的XPath选项的值(属性值的名称要准确)。因为我们知道我们的options.xml文件的细节,它给我们检索的字符串值转换到正确的数据类型。
使用OptionsManager类
这里是使用了Windows Mobile项目的OptionsManager类的步骤:创建options.xml文件,并把它嵌入的资源。提示:样品options.xml文件作为模板使用。确保options.xml文件中的LoadDefault方法的命名空间的引用是正确的。OptionsForm,Windows窗体,添加到项目中。这将是我们的选项对话框。添加一个TreeView控件和以下四个菜单项或按钮的OptionsForm:完成 - 保存更改选项和关闭选项对话框取消 - 取消更改选项和关闭选项对话框 默认的选项 - 恢复其默认值(如嵌入的资源存储的Options.xml指定)更改值 - 改变相应的选项的值的值表明了TreeView选择光标像这样OptionsForm的负载线和Closed事件处理程序:
private void OptionsForm_Load(object sender, EventArgs e)

{

    LoadTreeView();

} 





private void OptionsForm_Closed(object sender, EventArgs e)

{

    if (this.DialogResult == DialogResult.OK)

        OptionsManager.Save();

    else

        OptionsManager.Cancel();

} 





private void LoadTreeView()

{

    OptionsManager.LoadToTreeView(treeView1); 





    //expand the first level

    TreeNodeCollection nodes = treeView1.Nodes;

    foreach (TreeNode n in nodes)

        n.Expand();

}
线像这样的TreeView控件的KeyPress和AfterSelect事件处理程序:
private void treeView1_KeyPress(object sender, KeyPressEventArgs e)

{

    if (OptionsManager.IsValueNode(treeView1.SelectedNode))

    {

        OptionsManager.ChangeValue(treeView1.SelectedNode);

    }

    else

    {

        if (treeView1.SelectedNode.IsExpanded)

            treeView1.SelectedNode.Collapse();

        else

            treeView1.SelectedNode.Expand();

    }

} 



private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)

{

    //make the Change Value menu item available only when the current tree node is a value node

    menuMenuChangeValue.Enabled = OptionsManager.IsValueNode(treeView1.SelectedNode);

}
连接四个菜单项或按钮,像这样的Click事件处理程序:
private void menuDone_Click(object sender, EventArgs e)

{

    this.DialogResult = DialogResult.OK;   



}



private void menuMenuCancel_Click(object sender, EventArgs e)

{

    this.DialogResult = DialogResult.Cancel;

}





private void menuMenuDefault_Click(object sender, EventArgs e)

{

    OptionsManager.LoadDefault();

    LoadTreeView();

}





private void menuMenuChangeValue_Click(object sender, EventArgs e)

{

    OptionsManager.ChangeValue(treeView1.SelectedNode);

}
呼叫的项目中的任何地方的任何选项值GetOptionValue的方法。例如
int cacheSize = int.Parse(OptionsManager.GetOptionValue(

    "/group[@name='General']/option[@name='CacheSize']"));

bool sharePhotos = bool.Parse(OptionsManager.GetOptionValue(

    "/group[@name='SecurityPrivacy']/group[@name='SharedContents']/option[@name='Photos']"));
进一步改善
选项组件可在以下几个方面进一步改进:验证对一个XSD架构Options.xml。通过ImageList控件树中的节点添加图标。允许只有一个,同一级别的组或选项节点展开一次。这种模式是可取的小屏幕尺寸的。结论
一个TreeView基础的备选方案,提出并实施了为Windows Mobile组件。它有几个超过传统的设计选项对话框方式优势。这些包括消除布局的问题,有效地利用屏幕面积,直观,一致的用户界面,和声音坚持和组织应用程序设置结构的支持。
您可以下载下面的源代码:
{A1}

回答

评论会员:s 时间:2