2009-09-11 127 views
0

我創建一個時間選擇器用戶控件,首先顯示當天的一個按鈕,然後在接下來的幾天:ASP.NET:按鈕的OnClick事件和匿名事件不觸發

|今天| |星期一| |星期二| |星期三|

當用戶點擊的按鈕中的一個時,控制將顯示下面的天按鈕一套小時按鈕:

|今天| |星期一| |星期二| |星期三|

| 7:00 | | 8:00 | | 9:00 | | 10:00 | | 11:00 | |中午| | 1:00 | | 2:00 |

到目前爲止,我的控件工作得很好。然後,當用戶點擊一個小時按鈕時應該發生的事情是,一小部分按鈕(相隔5分鐘)將在那一小時顯示:

|今天| |星期一| |星期二| |星期三|

| 7:00 | | 8:00 | | 9:00 | | 10:00 | | 11:00 | |中午| | 1:00 | | 2:00 |

| 9:00 | | 9:05 | | 9:10 | | 9:15 | | 9:20 | | 9:25 | | 9:30 | | 9:35 |

而不是發生這種情況,控制似乎自行重置,並返回到它只顯示日按鈕的部分。小時按鈕的OnClick事件甚至不會觸發(我通過重載OnClick方法並將Page.Response.Write(「它的觸發」)放入它中來測試它 - 當我將它放入一個重載的OnClick方法中時,當天按鈕)。

這裏是我的代碼(一切都放在與代碼的用戶控制 - 在的.ascx標記頁面僅包含< @%控制%>標籤):

public partial class TimePicker : System.Web.UI.UserControl 
{ 
    public TimePicker() 
    { 
     this.Controls.Add(new TeeTimePanel()); 
    } 

    private class TimePanel : Panel 
    { 
     public TimePanel() 
     { 
      Days = new Panel(); 
      this.Controls.Add(Days); 

      Hours = new Panel(); 
      this.Controls.Add(Hours); 

      Minutes = new Panel(); 
      this.Controls.Add(Minutes); 

      DayButton.CreateDayButtons(this); 
     } 

     public void CreateHourButtons(DateTime day) 
     { 
      HourButton.CreateHourButtons(day, this); 
     } 

     public void CreateMinuteButtons(DateTime time) 
     { 
      MinuteButton.CreateMinuteButtons(time.Date, time.Hour, this); 
     } 

     public Panel Days, Hours, Minutes; 
    } 

    private class DayButton : Button 
    { 
     private DayButton(DateTime day, TimePanel parent) 
     { 
      this.date = day; 

      if (day.Date == DateTime.Today) 
      { 
       this.Text = "Today"; 
      } 
      else 
      { 
       this.Text = day.ToString("dddd"); 
      } 

      this.Click += delegate 
      { 
       parent.CreateHourButtons(day); 
      }; 
     } 

     private DateTime date; 

     public static void CreateDayButtons(TimePanel parent) 
     { 
      for (int i = 0; i < 5; i++) 
      { 
       DayButton b = new DayButton(DateTime.Today.AddDays(i), parent); 
       parent.Days.Controls.Add(b); 
      } 
     } 
    } 

    private class HourButton : Button 
    { 
     private HourButton(DateTime day, int hour, bool enabled, TimePanel parent) 
     { 
      this.Enabled = enabled; 
      this.time = day.Date.AddHours(hour); 

      if (hour < 12) 
      { 
       this.Text = hour.ToString() + ":00"; 
      } 
      else if (hour == 12) 
      { 
       this.Text = "Noon"; 
      } 
      else 
      { 
       this.Text = (hour - 12).ToString() + ":00"; 
      } 

      this.Click += delegate 
      { 
       parent.CreateMinuteButtons(day.AddHours(hour)); 
      }; 
     } 

     public static void CreateHourButtons(DateTime day, TimePanel parent) 
     { 
      Dictionary<int, bool> availableHours = new Dictionary<int, bool>(); 

      //This randomly generates available hours and will eventually 
      //be replaced with code that accesses a database 
      Random r = new Random(); 
      for (int i = 7; i <= 19; i++) 
      { 
       availableHours.Add(i, r.Next(5) != 0); 
      } 

      foreach (KeyValuePair<int, bool> kvp in availableHours) 
      { 
       HourButton b = new HourButton(day.Date, kvp.Key, kvp.Value, parent); 
       parent.Hours.Controls.Add(b); 
      } 
     } 

     private DateTime time; 
    } 

    private class MinuteButton : Button 
    { 
     private MinuteButton(DateTime day, int hour, int minute) 
     { 
      this.time = day.Date.AddHours(hour).AddMinutes(minute); 

      if (hour <= 12) 
      { 
       this.Text = hour.ToString() + ":"; 
      } 
      else 
      { 
       this.Text = (hour - 12).ToString() + ":"; 
      } 

      this.Text += minute.ToString("d2"); 
     } 

     public static void CreateMinuteButtons(DateTime day, int hour, Panel target) 
     { 
      List<int> availableTimes = new List<int>(); 

      //This randomly generates available times 
      Random r = new Random(); 
      for (int i = 0; i < 60; i += 5) 
      { 
       if (r.Next(2) != 0) 
       { 
        availableTimes.Add(i); 
       } 
      } 

      foreach (int i in availableTimes) 
      { 
       MinuteButton b = new MinuteButton(day, hour, i); 
       target.Controls.Add(b); 
      } 
     } 

     private DateTime time; 
    } 
} 

任何人都可以解釋爲什麼匿名方法爲DayButton工作,但是當我爲HourButton使用幾乎相同的代碼時,它不會?我確信它與ASP.NET的工作方式有關,而不是C#。

+1

您的<@%Control%>是否啓用了viewstate? – 2009-09-11 05:32:23

+0

如果您添加了用於顯示此控件的頁面代碼,將會非常有幫助。 – ChaosPandion 2009-09-11 18:50:11

+0

在默認情況下。aspx頁面我把這個: 2009-09-11 19:04:29

回答

1

確保您重新制作了回發控件或事件不會觸發。

+0

好吧,我理解了這個想法。我重載了TimePanel構造函數兩次,因此它可能需要日期和時間的爭論: public TeeTimePanel(DateTime day,int hour) { ... DayButton.CreateDayButtons(this); HourButton.CreateHourButtons(day,this); MinuteButton.CreateMinuteButtons(day,hour,this); } 我爲TimePanel創建的兩個新構造函數將重建控件,但我不知道如何讓控件的構造函數 - public TimePicker() - 決定使用哪個TimePanel的構造函數。 – 2009-09-11 18:16:50

0

你說得對,這是一個比c#更多的asp.net問題。您需要了解頁面的生命週期。當我第一次開始使用webforms並且獲得了很多新人的時候,這讓我感到困惑。當您初始化您的TimePicker控件時,構造函數運行並調用此方法:DayButton.CreateDayButtons(this);這將創建您的DayButtons。

this.Click += delegate 
{ 
    parent.CreateHourButtons(day); 
}; 

有了這段代碼,你試圖在一個按鈕上觸發一個事件,ASP.NET不知道任何事情,因爲它是動態添加到頁面上的。正如ChaosPandion所說,控件不會存在於頁面上,直到您再次添加它們,因此您的活動將如何被解僱?

爲我動態添加控件一直是關於回發和獲取值的頭痛等。我個人會考慮做類似於客戶端的事情。