Avatar billede segato Nybegynder
19. juni 2011 - 20:16 Der er 1 kommentar

Dynamisk tilføjelse af kontroller i compositecontrol

Jeg har en CompositeControl hvor jeg tilføjer en bunke DropDownList og knapper. Alle kontroller genereres på ny ved hvert postback med de samme ID via en Controls.Clear. Problem er hvis jeg i button click event ikke gør noget, skal jeg klikke to gange på knap før man ser de nyeste tilføjet kontroller. Kalder jeg CreateChildControls i click handler så ser jeg korrekt de nye kontroller, men så mister jeg ViewState på mine dropdowns. Hvad er den rigtige apporach til dette (se evt kode nedenstående):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using Test.Common;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web;

namespace Test.Controls
{
    public class OpenHour : CompositeControl, INamingContainer, IPostBackDataHandler
    {
        public OpenHour()
        {
          // EnsureChildControls();
        }

        //protected override void OnInit(EventArgs e)
        //{
        //    base.OnInit(e);
        //    this.EnsureChildControls();
        //}

     

        protected override void CreateChildControls()
        {       
            if (ChildControlsCreated)                                   
                return;

            base.Controls.Clear();         
            CreateControlHierarchy();
            ChildControlsCreated = true;
        }

        void CreateControlHierarchy()
        {
            if (Items == null)
            {
                InitItems();
            }

            Table tblOuter = new Table();

            foreach (Weekday day in Enum.GetValues(typeof(Weekday)))
            {
                var intervals = Items.Where(p => p.DayOfWeek == day).First();
                AddOpenHourIntervalRow(tblOuter, intervals, day);
            }

            this.Controls.Add(tblOuter);
        }       

        void AddOpenHourIntervalRow(Table table, OpenHourIntervalCollection itemsForCurrentDay, Weekday day)
        {
            bool firstItem = true;
            foreach (OpenHourInterval interval in itemsForCurrentDay)
            {
                List<BaseCell> row = new List<BaseCell>();

                string dayText = day.ToString();

                TimePicker timePickerStart = new TimePicker();
                timePickerStart.ID = "timePickerStart" + interval.Id.ToString();

                TimePicker timePickerEnd = new TimePicker();
                timePickerEnd.ID = "timePickerEnd" + interval.Id.ToString();           
               
                if (firstItem)
                    row.Add(new TextCell(dayText));
                else
                    row.Add(new TextCell(string.Empty));

                row.Add(new ControlCell(timePickerStart));
                row.Add(new TextCell("Til"));
                row.Add(new ControlCell(timePickerEnd));

                interval.TimePickerStartId = timePickerStart.ID;
                interval.TimePickerEndId = timePickerEnd.ID;

                HtmlGenericControl spanButtons = new HtmlGenericControl("span");

                if (firstItem)
                {
                    ImageButtonOpenHour imgbtnAdd = GetImageButton("ImageButtonWeekdayAdd", "/Images/16x16/add.png", day, interval.Id, new ImageClickEventHandler(imgbtnAdd_Click));
                    ImageButtonOpenHour imgbtnLock = GetImageButton("ImageButtonWeekdayLock", "/Images/16x16/lock.png", day, interval.Id, new ImageClickEventHandler(imgbtnLock_Click));
                    ImageButtonOpenHour imgbtnOpen = GetImageButton("ImageButtonWeekdayOpen", "/Images/16x16/key.png", day, interval.Id, new ImageClickEventHandler(imgbtnOpen_Click));

                    spanButtons.Controls.Add(imgbtnAdd);
                    spanButtons.Controls.Add(imgbtnLock);
                    spanButtons.Controls.Add(imgbtnOpen);

                    if (itemsForCurrentDay.Enabled)
                    {
                        imgbtnLock.Visible = true;
                        imgbtnAdd.Visible = true;
                        imgbtnOpen.Visible = false;
                    }
                    else
                    {
                        imgbtnLock.Visible = false;
                        imgbtnAdd.Visible = false;
                        imgbtnOpen.Visible = true;
                    }
                }
                else
                {
                    ImageButtonOpenHour imgbtnDelete = GetImageButton("ImageButtonWeekdayDelete" + interval.Id.ToString(), "/Images/16x16/delete.png", day, interval.Id, new ImageClickEventHandler(imgbtnDelete_Click));
                    spanButtons.Controls.Add(imgbtnDelete);
                }

                row.Add(new ControlCell(spanButtons));
               
                table.AddRow(row.ToArray());
             
                firstItem = false;
            }
        }

        ImageButtonOpenHour GetImageButton(string id, string url, Weekday day, Guid intervalId, ImageClickEventHandler clickHandler)
        {
                ImageButtonOpenHour btn = new ImageButtonOpenHour();

                btn.ID = id + "_" + day.ToString();
                btn.ImageUrl = url;
                btn.Weekday = day;
                btn.IntervalId = intervalId;
                btn.Click += clickHandler;

            return btn;
        }

        void imgbtnDelete_Click(object sender, ImageClickEventArgs e)
        {
            ImageButtonOpenHour btn = sender as ImageButtonOpenHour;
            var intervals = Items.Where(p => p.DayOfWeek == btn.Weekday).First();
            var interval = intervals.Find(p => p.Id == btn.IntervalId);
            intervals.Remove(interval);
            CreateChildControls();
        }

        void imgbtnOpen_Click(object sender, ImageClickEventArgs e)
        {
            ImageButtonOpenHour btn = sender as ImageButtonOpenHour;

            var intervals = Items.Where(p => p.DayOfWeek == btn.Weekday).First();
            intervals.Enabled = true;

            CreateChildControls();
        }

        void imgbtnLock_Click(object sender, ImageClickEventArgs e)
        {
            ImageButtonOpenHour btn = sender as ImageButtonOpenHour;

            var intervals = Items.Where(p => p.DayOfWeek == btn.Weekday).First();
            intervals.Enabled = false;

            CreateChildControls();
        }

        void imgbtnAdd_Click(object sender, ImageClickEventArgs e)
        {
            ImageButtonOpenHour btn = sender as ImageButtonOpenHour;         

            OpenHourInterval interval = new OpenHourInterval();
            interval.Start = default(DateTime);
            interval.End = default(DateTime);
           
            var intervalCollection = Items.Where(p=>p.DayOfWeek == btn.Weekday).First();
            intervalCollection.Add(interval);

            ChildControlsCreated = false;

            //Page.Response.Redirect(Page.Request.Url.AbsoluteUri);
            //CreateGui();
            // EnsureChildControls();
            //Page.Response.Write("<body OnLoad='java script:__doPostBack('ForcePostBack','');'>");
           
           
            //CreateControlHierarchy();
           
            //CreateChildControls();       
        }   

        void InitItems()
        {
            List<OpenHourIntervalCollection> intervals = new List<OpenHourIntervalCollection>();

            foreach (Weekday day in Enum.GetValues(typeof(Weekday)))
            {
                OpenHourIntervalCollection intervalCollection = new OpenHourIntervalCollection();
                intervalCollection.DayOfWeek = day;
                intervalCollection.Enabled = true;

                OpenHourInterval interval = new OpenHourInterval();
                interval.Start = default(DateTime);
                interval.End = default(DateTime);
               

                intervalCollection.Add(interval);
                intervals.Add(intervalCollection);
            }

            Items = intervals;
        }

        public List<OpenHourIntervalCollection> Items
        {
            get
            {
                return ViewState["Items"] as List<OpenHourIntervalCollection>;
            }
            set
            {
                ViewState["Items"] = value;
            }
        }         
     
    }
}
Avatar billede segato Nybegynder
19. juni 2011 - 20:42 #1
Hvis der er nogen der vil lege med det har jeg lavet et mere simpelt eksempel:

public class Test : CompositeControl
    {
        protected override void CreateChildControls()
        {
            Controls.Clear();
            CreateControlHierarchy();
        }

        void CreateControlHierarchy()
        {
            Button btn = new Button();
            btn.Text = "Add";
            btn.ID = "btn";
            btn.Click += new EventHandler(btn_Click);
           
           
            Table tbl = new Table();
            TableRow tr = new TableRow();
            TableCell td = new TableCell();
            td.Controls.Add(btn);
            tr.Cells.Add(td);
            tbl.Rows.Add(tr);

            foreach (string info in Items)
            {
                tr = new TableRow();
                td = new TableCell();

                DropDownList dl = new DropDownList();
                dl.ID = info;

                dl.Items.Add("1");
                dl.Items.Add("2");

                td.Controls.Add(dl);
                tr.Cells.Add(td);
                tbl.Rows.Add(tr);
            }

            this.Controls.Add(tbl);
        }

        void btn_Click(object sender, EventArgs e)
        {
            Items.Add(Guid.NewGuid().ToString());
        }

        public List<string> Items
        {
            get
            {
                if (ViewState["Items"] == null)
                    ViewState["Items"] = new List<string>();

                return ViewState["Items"] as List<string>;
            }
            set
            {
                ViewState["Items"] = value;
            }
        }
    }
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

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



IT-JOB

Saab Danmark A/S

Infrastructure Architect

Bunker Holding A/S

Director of Technology

Cognizant Technology Solutions Denmark ApS

Graduate - Software Automation Program

Metroselskabet og Hovedstadens Letbane

IT Full Stack-udvikler