在 ASP.NET 中创建一个带有一系列 ? 的故障排除网页。 有向图

发布于 2024-07-23 23:56:36 字数 8539 浏览 5 评论 0原文

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

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

由于我不太熟悉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;
    }


}

I've been working on my first web page which will be used as a trouble shooting guide based on a series of questions. The questions are determined by the answer of the previous question, so it turns into a "choose your own adventure". Luckily I was given a decision flow chart showing all the possible paths, but it looks like the Tokyo subway map. I first created a series of panels, each containing the question and a dropdown list control containing the answer as the text and the id of the panel it should preceed. Next I created a class to organize all the panels into a graph structure. With this class I'm able to know the order of which panels are selected, which panels have not been selected, and is easy to make changes to the decision flow.

Below is an example of how I am using the class in the pageload event and below that is the actual class.

Since I'm not really familiar with asp.net, I'm just wondering if there are better ways of tackling this problem and if there are flaws within my code. My code is working, but I'm sure there could be improvements.

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;
    }
}

Here is the class

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;
    }


}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泪是无色的血 2024-07-30 23:56:36

没有浏览您的代码,但根据您想要执行的操作的想法,我认为您可能想使用 WizardControl http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.wizard.aspx 允许要创建高度可定制的向导

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

Not gone through your code but based on the idea of what you want to do I think you might want to investigate using the WizardControl http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.wizard.aspx which allows for highly customisable Wizards to be created

As a first step you could use the ActiveStepChanged event to decide which Step to go to depending on what the user answers in each step.

两仪 2024-07-30 23:56:36

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

看起来您正在为每个 page_load 构建整个图表 - 您是否在回发后浏览该结构?

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

I strongly recommend against referencing any instance of System.Web.Page from within your DecisionGraph class. It doesn't look like you're using the reference for anything right now and you'll just be tempted to use it unnecesarrily for as long as you leave it in there.

It seems like you are building the entire graph for each page_load--are you navigating through the structure after postbacks?

Keep in mind that when you set a panel's visibility property to false you are not getting any output on the client side. However, if you set the CSS style attribute "display" to "none" then you will be rendering the entire graph to the client and can actually perform all of the navigation on the client-side with javascript.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文