1

我一直在制作我的第一个网页,该网页将用作基于一系列问题的故障排除指南。题目由上一题的答案决定,因此变成了“选择自己的冒险”。幸运的是,我得到了一张显示所有可能路径的决策流程图,但它看起来像东京地铁地图。我首先创建了一系列面板,每个面板都包含问题和一个下拉列表控件,其中包含作为文本的答案和它应该位于前面的面板的 ID。接下来我创建了一个类来将所有面板组织成一个图形结构。通过这个类,我能够知道选择哪些面板的顺序,哪些面板没有被选择,并且很容易对决策流程进行更改。

下面是我如何在 pageload 事件中使用该类的示例,下面是实际类。

由于我对 asp.net 不是很熟悉,我只是想知道是否有更好的方法来解决这个问题,以及我的代码中是否存在缺陷。我的代码正在运行,但我确信可能会有改进。

protected void Page_Load(object sender, EventArgs e)
{

    DecisionGraph g = new DecisionGraph(this);

    //  Pass is root panel
    g.BuildGraph("pnl1");

    //  Refreshes graph and returns an obj containing 2 iterable objects 
    DecisionGraphEnumeration dgEnum = g.RefreshGraph();

    //  Clear panel which will hold active panels
    pnlMASTER.Controls.Clear();

    IEnumerator<Panel> iEnumOnPath = dgEnum.GetOnPathPanelEnumerator();
    while (iEnumOnPath.MoveNext())
    {
        Panel p = (Panel)iEnumOnPath.Current;
        p.Visible = true;

        pnlMASTER.Controls.Add(p);
    }

    IEnumerator<Panel> iEnumOffPath = dgEnum.GetOffPathPanelEnumerator();

    while (iEnumOffPath.MoveNext())
    {
        iEnumOffPath.Current.Visible = false;
    }
}

这是课程

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Collections.Generic;


public class DecisionGraph
{

    const String NULL_POINTER_NAME = "null";
    private Node root;
    private Page webPage;

    //constructor
    public DecisionGraph(Page pg)
    {
        this.webPage = pg;
        this.root = null;
    }

    //  method creates a graph structure recursively starting
    //  with the parameter as root
    public void BuildGraph(String pnlName)
    {
        //  return the reference of the supplied panel
        Panel p = GetPanel(pnlName);

        // create root
        root = new Node(p, GetDropDownList(p));

        //  add children nodes to root
        insert(root);


        return;
    }

    //  adds all child nodes to passed node
    private void insert(Node n)
    {
        // if Panel has a DropDownList
        if (n.dropDownList != null)// not leaf
        {
            // create an array of Nodes to hold references to children
            n.children = new Node[n.dropDownList.Items.Count];

            int i = 0;
            foreach (ListItem it in n.dropDownList.Items)
            {
                Panel childPanel = GetPanel(it.Value);

                if (childPanel == null)
                {
                    //  Panel does not exit
                    n.children[i] = null;
                }
                else
                {

                    Node childNode = GetNode(childPanel);

                    if (childNode == null)//   Node doesn't exist in structure for chilePanel
                    {
                        //  create child node
                        childNode = new Node(childPanel, GetDropDownList(childPanel));

                        // add child node to arryay of children
                        n.children[i] = childNode;

                        // add the childs nodes of childNode to childNode
                        insert(n.children[i]);
                    }
                    else
                    {
                        // node had already been created, just add reference
                        n.children[i] = childNode;
                    }



                }

                i++;
            }
        }

        return;

    }

    //  returns an iterator of all active panels set as visible
    //  and sets all other panels as hidden
    public DecisionGraphEnumeration RefreshGraph()
    {
        LinkedList<Panel> pathedPanels = new LinkedList<Panel>();
        LinkedList<Panel> nonPathedPanels = new LinkedList<Panel>();

        FindCurrentPath(root, pathedPanels);

        HideNonPathedNodes(root, nonPathedPanels);

        UnMarkAllNodes(root);

        return new DecisionGraphEnumeration(pathedPanels.GetEnumerator(), nonPathedPanels.GetEnumerator());
    }

    //  marks each node as valid and saves reference inorder
    private void FindCurrentPath(Node n, LinkedList<Panel> list)
    {
        if (n == null)
            return;

        n.visitedFlag = true;
        list.AddLast(n.panel);

        if (n.dropDownList == null)
            return;

        int index = n.dropDownList.SelectedIndex;

        FindCurrentPath(n.children[index],list);

        return;

    }

    //  finds all non pathed nodes and saves reference in no order
    private void HideNonPathedNodes(Node n, LinkedList<Panel> list)
    {
        if (n == null)
            return;

        if (!n.visitedFlag)
        {

            n.ResetDropDownList();

            //  add panel if not already added.
            if (!list.Contains(n.panel))
                list.AddLast(n.panel);
        }

        if(n.children == null)
            return;

        foreach (Node childNode in n.children)
            HideNonPathedNodes(childNode, list);
    }

    // unmarks n and sets all children of n as unmarked
    private void UnMarkAllNodes(Node n)
    {
        if (n == null)
            return;

        n.visitedFlag = false;

        if (n.children == null)
        {
            return;
        }
        else
        {
            foreach (Node childNode in n.children)
                UnMarkAllNodes(childNode);
        }

    }

    // returns node if a node already exists for p in structure, else returns null
    private Node GetNode(Panel p)
    {
        Node n = getNode(root, p);

        return n;
    }

    // recursive method call for GetNode
    private Node getNode(Node n, Panel p)
    {
        if (n == null || p == null)
            return null;

        if (n.panel.Equals(p))
        {
            return n;
        }
        else if (n.children != null)
        {
            Node x = null;
            int i = 0;

            while (x == null && i < n.children.Length)
            {
                x = getNode(n.children[i], p);
                i++;
            }

            return x;
        }
        else
        {
            return null;
        }

    }

    //  returns a DropDownList from p
    private DropDownList GetDropDownList(Panel p)
    {

        foreach (Control ctrl in p.Controls)
        {
            if (ctrl is DropDownList)
            {
                return (DropDownList) ctrl;
            }
        }

        return null;
    }

    //  returns a panel from webpage of contructor using the FindControl method
    private Panel GetPanel(String panelName)
    {
        if(panelName.Equals(NULL_POINTER_NAME))
            return null;

        Control ctrl = webPage.FindControl(panelName);
        if (ctrl is Panel)
        {
            return (Panel)ctrl;
        }
        else
        {
            throw new ArgumentException(String.Format("{0} is not a Panel inside page {1}",panelName,webPage.Title.ToString()));
        }
    }


    private class Node
    {
        public Panel panel;
        public DropDownList dropDownList;
        public Node[] children;
        public bool pathedNode;
        public bool visitedFlag;

        #region Constructors

        public Node() : this(null, null) { }

        public Node(Panel p) : this(p, null) { }

        public Node(Panel pnl, DropDownList d)
        {
            this.panel = pnl;
            this.dropDownList = d;
            this.children = null;
            this.pathedNode = false;
            this.visitedFlag = false;
        }

        #endregion

        public void ResetDropDownList()
        {
            if (dropDownList == null)
                return;
            else
                dropDownList.SelectedIndex = 0;
        }
    }
}


public class DecisionGraphEnumeration
{
    private IEnumerator<Panel> onPathPanels;
    private IEnumerator<Panel> offPathPanels;

    internal DecisionGraphEnumeration(IEnumerator<Panel> active, IEnumerator<Panel> nonActive)
    {
        onPathPanels = active;
        offPathPanels = nonActive;
    }

    public IEnumerator<Panel> GetOnPathPanelEnumerator()
    {
        return onPathPanels;
    }

    public IEnumerator<Panel> GetOffPathPanelEnumerator()
    {
        return offPathPanels;
    }


}
4

2 回答 2

1

没有通过您的代码,但基于您想要做什么的想法,我认为您可能想使用 WizardControl http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols 进行调查。 Wizard.aspx允许创建高度可定制的向导

作为第一步,您可以使用 ActiveStepChanged 事件根据用户在每个步骤中的回答来决定要转到哪个步骤。

于 2009-06-09T14:28:04.683 回答
0

我强烈建议不要在 DecisionGraph 类中引用任何 System.Web.Page 实例。看起来您现在没有将参考用于任何事情,只要您将其留在其中,您就会很想不必要地使用它。

似乎您正在为每个 page_load 构建整个图表——您是否在回发后浏览该结构?

请记住,当您将面板的可见性属性设置为 false 时,您不会在客户端获得任何输出。但是,如果您将 CSS 样式属性“display”设置为“none”,那么您会将整个图形呈现给客户端,并且实际上可以使用 javascript 在客户端执行所有导航。

于 2009-06-09T14:38:02.620 回答