Avatar billede bjornhart Nybegynder
27. maj 2006 - 19:50 Der er 13 kommentarer og
1 løsning

TreeNode med buttons

Jeg vil gerne lave en TreeNode med x-antal buttons som udfører serverside kode. Jeg har lavet en klasse som arver fra TreeNode og ændret i RenderPreText-metoden således, at når noden bliver renderet så indeholder den en button.

public class MyTreeNode : TreeNode
    {
        protected override void RenderPreText(System.Web.UI.HtmlTextWriter writer)
        {
            Button btn = new Button();
            btn.Text = "new button";
            btn.ID = "btn1";
           
            btn.CommandArgument = "test";
         
            btn.RenderControl(writer);
        }
}

Hvordan fanger jeg click-eventen fra button'en i treenoden?
Avatar billede snepnet Nybegynder
27. maj 2006 - 20:31 #1
Prøv at se om du kan fikse det ved en
btn.Click += new EventHandler(btn_Click);

Og en handler:
void btn_Click(object sender, EventArgs e)
{
  // din handlerkode
}

Og definér din klasse sådan her:
public class MyTreeNode : TreeNode, INamingContainer

Mvh
Avatar billede bjornhart Nybegynder
27. maj 2006 - 21:41 #2
Desværre det virkede ikke.

Selve klassen MyTreeNode er placeret i en seperat .cs-fil. Kan jeg på nogen måde få adgang til de objekter der er placeret på siden default.aspx.
Jeg tænker her på om jeg i min handler btn_Click kunne få adgang til label1.text og sætte den til "event fanget".
Avatar billede snepnet Nybegynder
27. maj 2006 - 23:00 #3
Mmmm.... Det kan du sådan set godt, men er det ikke nemmere blot at debugge, og se om du rammer din handler?
Du er velkommen til at poste hele koden vedr. dit treeview - så prøver jeg det lige her.
Mvh
Avatar billede bjornhart Nybegynder
28. maj 2006 - 12:38 #4
Jeg har prøvet at debugge.

Her kommer koden i default.aspx.cs:

protected void Page_Load(object sender, EventArgs e)
{
MyTreeNode nodee = new MyTreeNode();
TreeView1.Nodes.Add(nodee);
}

Og selve def. af treeNoden, CustomTreeNode.cs:
public class MyTreeNode : TreeNode, INamingContainer
{
        protected override void RenderPreText(System.Web.UI.HtmlTextWriter writer)
        {
            Button btn = new Button();         
            btn.Text = "new button";
            btn.Click += new EventHandler(btn_Click);
            btn.RenderControl(writer);
        }

        void btn_Click(object sender, EventArgs e)
        {
            // din handlerkode
            string str = "test"; 
        }
}
Avatar billede snepnet Nybegynder
28. maj 2006 - 15:04 #5
Hvis du skal sikre at det er dine noder der bliver benyttet - må du specialisere et treeview også. Ellers vil din pretext forsvinde hvis du ikke generer dit treeview hver gang.

public class MyTreeView : TreeView
{
    protected override TreeNode CreateNode()
    {
        return new MyTreeNode();
    }
}

Mht. til det med at håndtere events, så har jeg kigget lidt på det, og det er ikke helt så snildt som det måske kunne have været.
Det er ikke nødvendigvis det hele du skal bruge, men hvis du vil have fat i den node knapklikket er fyret fra i din eventhandler - skal du lave noget meget tilsvarende:
(Der er ikke noget aspx-kode).

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;

public partial class _Default : System.Web.UI.Page
{
    MyTreeView tree = null;
   
    protected void Page_Load(object sender, EventArgs e)
    {               
        if (!IsPostBack)
        {
            MyTreeNode n1 = new MyTreeNode(tree);
            n1.Text = "N1";
            tree.Nodes.Add(n1);

            MyTreeNode n2 = new MyTreeNode(tree);
            n2.Text = "N2";
            n1.ChildNodes.Add(n2);

            MyTreeNode n3 = new MyTreeNode(tree);
            n3.Text = "N3";
            n1.ChildNodes.Add(n3);
        }
    }

    protected override void OnInit(EventArgs e)
    {
        tree = new MyTreeView();
        tree.SelectedNodeChanged += new EventHandler(tree_SelectedNodeChanged);
        tree.ButtonClicked += new TreeButtonClickedEventHandler(tree_ButtonClicked);
        form1.Controls.Add(tree);
        base.OnInit(e);
    }

    void tree_ButtonClicked(object treeView, TreeButtonClickedEventArgs e)
    {
        Response.Write("A button on a node is clicked");
    }

    void tree_SelectedNodeChanged(object sender, EventArgs e)
    {
        Response.Write("A node is selected");
    } 
}

// Delegate for TreeButtonClick-eventhandlers
public delegate void TreeButtonClickedEventHandler(object treeView, TreeButtonClickedEventArgs e);

// Specielt argment, så du har let adgang til noden der er klikket på
public class TreeButtonClickedEventArgs : EventArgs
{
    private TreeNode m_Node;

    public TreeNode Node
    {
        get { return m_Node; }
        set { m_Node = value; }
    }
   
    public TreeButtonClickedEventArgs(TreeNode node)
    {
        this.m_Node = node;
    }
}

// Custom treeview - så du sikrer at dine egne noder bliver benyttet
// Desuden publicerer det så ButtonClicked eventet
public class MyTreeView : TreeView
{
    public event TreeButtonClickedEventHandler ButtonClicked;

    protected virtual void OnButtonClicked(TreeButtonClickedEventArgs e)
    {
        if (ButtonClicked != null)
        {
            ButtonClicked(this, e);
        }
    }

    //
    protected override TreeNode CreateNode()
    {
        return new MyTreeNode(this);
    }

    // Overskrivning af treeview'ets raisepostbackevent - så eget prefix kan håndteres.
    // Hvis det ikke er eget prefix der er benyttet - benyttes basens implementering.
    // Dette skal sikre at de vanlige event fyres.
    protected override void RaisePostBackEvent(string eventArgument)
    {
        if (eventArgument[0] == 'b')
        {
            string nodePath = eventArgument.Substring(1);
            TreeNode node = this.FindNode(nodePath);
            OnButtonClicked( new TreeButtonClickedEventArgs(node) );
        }
        else
        {
            base.RaisePostBackEvent(eventArgument);
        }
  }
}

// custom treenode - definerer sit eget kommandoprefix, så knapper kan kendes fra de andre kommandoer
public class MyTreeNode : TreeNode
{
    protected const string ButtonCommandPrefix = "b";

    private TreeView m_Tree;

    public TreeView Tree
    {
        get { return m_Tree; }
        set { m_Tree = value; }
    }

    // I eksemplet her er det så et krav at din noder instantieres med et treeview, hvilet
    // er nødvendigt for at få fat i kontrollen (treeview'et) der skal håndtere kommandoen
    public MyTreeNode(TreeView tree)
    {
        m_Tree = tree;
    }

    protected override void RenderPreText(System.Web.UI.HtmlTextWriter writer)
    {
        Page page = HttpContext.Current.Handler as Page;
        writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
        writer.AddAttribute(HtmlTextWriterAttribute.Onclick, page.ClientScript.GetPostBackClientHyperlink(m_Tree, ButtonCommandPrefix + this.ValuePath));
        writer.RenderBeginTag(HtmlTextWriterTag.Input);       
        writer.RenderEndTag();
    }   
}

Mvh
Avatar billede snepnet Nybegynder
28. maj 2006 - 15:05 #6
Det fra
using System;
Og til
Mvh

Kan du bare kopiere direkte ind i din codebehind, hvis du har en Default.aspx alligevel.

Mvh
Avatar billede bjornhart Nybegynder
28. maj 2006 - 16:55 #7
Det virker! Super!!! hvordan får jeg fat i ButtonCommandPrefix'et i tree_ButtonClicked?
Avatar billede snepnet Nybegynder
28. maj 2006 - 17:11 #8
Du kan enten bare skrive det direkte - eller gøre denne her public:
protected const string ButtonCommandPrefix = "b";
Så den bliver til
public const string ButtonCommandPrefix = "b";

Så kan du få den uden for klassen ved at kalde:
MyTreeNode.ButtonCommandPrefix;

Mvh
Avatar billede snepnet Nybegynder
28. maj 2006 - 17:14 #9
(de allerede eksisterende er faktisk hardcodet i TreeView-klassen - men kun 't' og 's' er benyttet i forvejen)
Mvh
Avatar billede bjornhart Nybegynder
28. maj 2006 - 17:40 #10
Ja okay. Det jeg var interesseret i var at give de enkelte knapper et forskelligt prefix så jeg i tree_ButtonClicked kunne afgøre hvilken knap der blev trykket på. Så det var muligt at have flere knapper på den enkelte node. Var det ikke det der var meningen med ButtonCommandPrefix ?
Avatar billede snepnet Nybegynder
28. maj 2006 - 17:46 #11
Eventhåndtering er TreeView'et er (som det nu er bygget) baseret på prfixes på kommandoargumentet - 't' for toggle og 's' for select.
Eksemplet du har fået bygger bare videre på samme model - men benytter blot et andet prefix på kommandoargumentet.
Du kan arbejde med alle de prefixes du vil ... blot du ikke snupper dem treeview'et bruger i forvejen (altså t og s), eller bruger nogle der gør at der går kludder i udledning af hvilken node der er trykket på.
Hvis du sætter et breakpoint i RaisePostBackEvent på MyTreeView - kan du se navnekonventionen for argumentet.
Mvh
Avatar billede bjornhart Nybegynder
28. maj 2006 - 20:09 #12
Jeg takker mange gange, virkeligt genialt. Send lige et svar. ps. Er det nemt at tilføje et input-felt i samme treenode og fange teksten i tree_ButtonClicked?
Avatar billede snepnet Nybegynder
28. maj 2006 - 20:40 #13
Det var så lidt :o)
Det bliver nok lidt noget pilleri... En TreeNode er ikke nogen kontrol (Control), så den er lidt anderledes.
Prøv at læg din textbox ind sådan her:

TextBox tb = new TextBox();
tb.ID = "input_" + this.ValuePath;
tb.RenderControl(writer);

Så skulle du kunne finde den igen i handleren i dit treeview:
string text = this.Page.Request.Form["input_" + nodePath];

Ikke særlig labert - men det kan jo være en start ;o)

Mvh
Avatar billede bjornhart Nybegynder
28. maj 2006 - 21:06 #14
Jeg er ligeglad med at det ikke er labert! Det virker. Her er points fuldt fortjent. sensai
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester