Bonjour,

Je vous explique le topo : j'ai un TreeView. Lorsque l'on clique sur un de ses noms, un certain nombre d'informations le concernant sont récupérées dans le fichier XML source pour être affichées, notamment ses noeuds enfants. Ceux-ci peuvent être d'un nombre "très" variable, donc je dois les ajouter dans un PlaceHolder dynamiquement.

Par la suite je souhaite que l'utilisateur puisse cliquer sur un bouton "PLUS" afin de faire apparaitre autant de TextBox supplémentaires qu'il le souhaite, afin d'y saisir des informations et finalement les enregistrer dans le fichier XML source.

Je ne vous cache pas que tous ces besoins créent un beau pataquès dès qu'il s'agit de créer la logique de PostBack.

J'ai trouvé cette vidéo de Joe Stagner, qui m'a vaguement aidé, mais évidemment mes besoins sont légèrement différents de ce qu'il y explique.

Voilà où j'en suis niveau code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<asp:XmlDataSource ID="XmlDataSourceGeo" runat="server" DataFile="~/App_Data/thesaurus-Geographique-Sample.xml"
    XPath="/thesaurus/*" CacheExpirationPolicy="Sliding" CacheDuration="60" />
<asp:TreeView ID="TreeViewGeo" runat="server" DataSourceID="XmlDataSourceGeo" ExpandDepth="0" ShowLines="true" SkipLinkText="" OnSelectedNodeChanged="TreeViewGeo_SelectedNodeChanged"
    OnTreeNodeDataBound="TreeViewGeo_DataBound">
    <DataBindings>
        <asp:TreeNodeBinding DataMember="retenu" ValueField="id" TextField="terme" />
        <asp:TreeNodeBinding DataMember="EP" TextField="terme" FormatString="Employé pour : {0}" SelectAction="None" />
    </DataBindings>
</asp:TreeView>
<table><tr><td>
<asp:UpdatePanel ID="UpdatePanelEP" runat="server">
    <ContentTemplate>
        <asp:PlaceHolder ID="PlaceHolderEP" runat="server" />
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="BoutonPlusEP" EventName="Click" />
    </Triggers>
</asp:UpdatePanel>
</td>
<td>
<asp:ImageButton ID="BoutonPlusEP" runat="server" ImageUrl="~/images/plus.gif" OnClick="BoutonPlusEP_Click" />
</td></tr></table>
Et surtout côté code behind :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System;
using System.Data;
using System.Xml;
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;
 
public partial class _Default : System.Web.UI.Page 
{
    static XmlDocument xmlDoc = new XmlDocument();
    static int nbTextBoxEP = 0;
    private TextBox[] textBoxEP;
 
    protected void Page_PreInit(object sender, EventArgs e)
    {
        Control monControl = GetPostBackControl(this.Page);
 
        if ((monControl != null))
        {
            if ((monControl.ClientID.ToString() == "BoutonPlusEP"))
            {
                nbTextBoxEP++;
            }
        }
    }
 
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        textBoxEP = new TextBox[nbTextBoxEP];
        for (int i = 0; i < nbTextBoxEP; i++)
        {
            TextBox textBox = new TextBox();
            textBox.ID = "TextBoxEP" + i;
            textBox.CssClass = "TextBoxEP";
            PlaceHolderEP.Controls.Add(textBox);
            textBoxEP[i] = textBox;
        }
    }
 
    protected void Page_Load(object sender, EventArgs e)
    {
        xmlDoc.Load(Server.MapPath("~/App_Data/thesaurus-Geographique-Sample.xml"));
        //TreeViewGeo.Nodes.Clear();
        //foreach (XmlNode noeudRetenu in xmlDoc.DocumentElement.SelectNodes("retenu"))
        //{
        //    AddNode(noeudRetenu, TreeViewGeo.Nodes);
        //}
        //TreeViewGeo.CollapseAll();
    }
 
    //protected void AddNode(XmlNode noeud, TreeNodeCollection collecNoeuds)
    //{
    //    collecNoeuds.Add(new TreeNode(noeud.Attributes["terme"].Value, noeud.Attributes["id"].Value));
    //    TreeNode newNoeud = collecNoeuds[collecNoeuds.Count - 1];
    //    if (noeud.HasChildNodes)
    //    {
    //        foreach (XmlNode noeudEnfant in noeud.SelectNodes("retenu"))
    //            AddNode(noeudEnfant, newNoeud.ChildNodes);
    //    }
    //}
 
    public static Control GetPostBackControl(Page maPage)
    {
        Control monControl = null;
        string nomControl = maPage.Request.Params.Get("__EVENTTARGET");
        if (((nomControl != null) && (nomControl != string.Empty)))
        {
            monControl = maPage.FindControl(nomControl);
        }
        else
        {
            foreach (string control in maPage.Request.Form)
            {
                Control testControl = maPage.FindControl(control);
                if (testControl is Button)
                {
                    monControl = testControl;
                }
            }
 
        }
        return monControl;
    } 
 
    protected void TreeViewGeo_DataBound(object sender, TreeNodeEventArgs e)
    {
        if (e.Node.Text.StartsWith("Employé pour : "))
            e.Node.Text = "<span style=\"color: #CF4DCF\">" + e.Node.Text + "</span>";
    }
 
    protected void TreeViewGeo_SelectedNodeChanged(object sender, EventArgs e)
    {
        TableInfos.Style.Add("display", "");
        if (TreeViewGeo.SelectedNode.Parent != null)
            LabelParent.Text = TreeViewGeo.SelectedNode.Parent.Text;
        TextBoxRetenu.Text = TreeViewGeo.SelectedNode.Text;
        XmlNodeList noeudsEP = xmlDoc.SelectSingleNode(TreeViewGeo.SelectedNode.DataPath).SelectNodes("EP");
        nbTextBoxEP = noeudsEP.Count;
        for (int i = 0; i < noeudsEP.Count; i++)
        {
            TextBox TextBoxEP = new TextBox();
            TextBoxEP.ID = "TextBoxEP" + i;
            TextBoxEP.CssClass = "TextBoxEP";
            TextBoxEP.Text = noeudsEP[i].Attributes["terme"].Value;
            PlaceHolderEP.Controls.Add(TextBoxEP);
        }
    }
 
    protected void BoutonPlusEP_Click(object sender, EventArgs e)
    {
        //TextBox TextBoxEP = new TextBox();
        //TextBoxEP.ID = "TextBoxEP" + PlaceHolderEP.Controls.Count;
        //TextBoxEP.CssClass = "TextBoxEP";
        //PlaceHolderEP.Controls.Add(TextBoxEP);
        //TextBoxEP.Focus();
    }
 
    protected void BoutonSauv_Click(object sender, EventArgs e)
    {
        foreach (TextBox textBox in textBoxEP)
        {
            Response.Write(textBox.Text);
        }
    }
}
Un problème qui se pose est que Joe Stagner montre comment ajouter les TextBox au moment de l'évènement OnInit de la page, mais il semble aussi qu'à ce moment là je ne peux pas déterminer quel est le nœud sélectionné dans le TreeView, et donc récupérer les infos dans le fichier XML (notamment le nombre de nœuds enfants).

De plus, lorsque l'on clique sur le bouton "PLUS", pour l'instant cela n'ajoute dans le meilleur des cas qu'une seule TextBox, pas plus...

Je suis désolé je me rends compte que mon code n'est sans doute pas très facile à lire et mon cas assez complexe à résoudre, mais je ne vois pas trop comment faire mieux. Peut-être en vous envoyant le code source s'il y a des volontaires.

Merci d'avance pour vos suggestions.