2009-06-09 10 views
1

Ich habe an meiner ersten Webseite gearbeitet, die anhand einer Reihe von Fragen als Leitfaden für die Fehlersuche verwendet wird. Die Fragen werden durch die Antwort der vorherigen Frage bestimmt, so dass es zu einem "Wählen Sie Ihr eigenes Abenteuer" wird. Glücklicherweise bekam ich ein Entscheidungsfließbild mit allen möglichen Wegen, aber es sieht aus wie die Tokioter U-Bahnkarte. Ich habe zuerst eine Reihe von Panels erstellt, die jeweils die Frage und ein Dropdown-Listen-Steuerelement enthielten, das die Antwort als Text und die ID des Panels enthielt, dem sie vorangehen sollte. Als Nächstes habe ich eine Klasse erstellt, um alle Panels in einer Graphenstruktur zu organisieren. Mit dieser Klasse kann ich die Reihenfolge der ausgewählten Panels kennen, welche Panels nicht ausgewählt wurden und kann leicht Änderungen am Entscheidungsfluss vornehmen.Erstellen einer Fehlersuche Webseite mit einer Reihe von? S in asp.net. Gerichtetes Diagramm

Unten ist ein Beispiel, wie ich die Klasse im Pageload-Ereignis verwende und darunter die eigentliche Klasse.

Da ich asp.net nicht wirklich kenne, frage ich mich nur, ob es bessere Möglichkeiten gibt, dieses Problem anzugehen, und ob es Fehler in meinem Code gibt. Mein Code funktioniert, aber ich bin mir sicher, dass es Verbesserungen geben könnte. Hier

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

ist die Klasse

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


} 

Antwort

1

Nicht durch den Code gegangen, aber basiert auf der Idee von dem, was Sie tun möchten, ich glaube, Sie möchten vielleicht die WizardControl http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.wizard.aspx untersuchen, indem die für hochgradig anpassbarer erlaubt Zu erstellende Assistenten

Als ersten Schritt können Sie das ActiveStepChanged-Ereignis verwenden, um zu entscheiden, welchen Schritt Sie ausführen möchten, je nachdem, was der Benutzer in jedem Schritt beantwortet.

0

Ich empfehle dringend, keine Instanz von System.Web.Page innerhalb Ihrer DecisionGraph-Klasse zu referenzieren. Es sieht nicht so aus, als ob du die Referenz für irgendetwas gerade verwendest und du wirst nur versucht sein, es unnötig zu benutzen, solange du es da drin lässt.

Es sieht so aus, als würden Sie die gesamte Grafik für jede page_load erstellen - navigieren Sie nach Postbacks durch die Struktur?

Beachten Sie, dass beim Festlegen der Sichtbarkeitseigenschaft eines Steuerfelds auf false keine Ausgabe auf der Clientseite erfolgt. Wenn Sie jedoch das CSS-Stilattribut "display" auf "none" setzen, rendern Sie das gesamte Diagramm für den Client und können die gesamte Navigation auf der Clientseite mit Javascript ausführen.

+0

Ich verweise System.Web.Page, wenn ich die FindControl-Methode – Kevin

+0

ausführen Sie können tatsächlich die FindControl-Funktion auf einem Ihrer Webcontrols, wie z. B. Ihre Panels aufrufen - unter Berücksichtigung, dass Sie nur die Kinder von suchen werden diese besondere Kontrolle. Dies wird tatsächlich schneller, da Sie nicht die ganze Seite durchsuchen. Allerdings habe ich festgestellt, dass Sie in BuildGraph finden Sie den Verweis auf die "Panel ID" Zeichenfolge, die Sie übergeben, so dass Sie in Erwägung ziehen könnte, die tatsächliche Panel-Referenz statt. – nvuono

Verwandte Themen