2011-05-12 78 views
1

我有這段代碼來創建和顯示月份日曆控件的形式。無法訪問處置對象「MonthCalendar」

private void showcalendar_Click(object sender, EventArgs e) 
{ 
    ShowCalendar(); 
} 

void ShowCalendar() 
{ 
    DateTime current5 = DateTime.Now.AddDays(-5); 

    MonthCalendar cal = new MonthCalendar(); 
    Panel panel = new Panel(); 
    Form f = new Form(); 

    cal.MaxSelectionCount = 1; 
    cal.SetDate(current5); 
    cal.DateSelected += new DateRangeEventHandler(DateSelected); 
    cal.ShowToday = true; 
    panel.Width = cal.Width; 
    panel.Height = cal.Height; 
    panel.BorderStyle = BorderStyle.FixedSingle; 
    panel.Controls.Add(cal); 
    f.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 
    f.ShowInTaskbar = false; 
    f.Size = panel.Size; 
    f.Location = MousePosition; 
    f.StartPosition = FormStartPosition.Manual; 
    f.Controls.Add(panel); 
    f.Deactivate += delegate { f.Close(); }; 
    f.Show(); 
} 

void DateSelected(object sender, DateRangeEventArgs e) 
{ 
    MonthCalendar cal = (MonthCalendar)sender; 
    Form f = cal.FindForm(); 
    f.Close(); 
} 

當我調用ShowCalendar MONTHCALENDAR控制顯示,我可以在其內選擇日期。問題是,當我點擊某個區域時(當前日期描述的最低點),我得到一個異常 - 「無法訪問已處理的對象。對象名稱:'MonthCalendar'。」我不知道這個例外如何產生,以及如何擺脫它。也許你有什麼想法?

我的應用程序不是多線程的,只是調用ShowCalendar函數的按鈕的簡單形式。

Calendar with area selected

+0

什麼是stackdump說? – 2011-05-12 09:36:34

+0

'f.Close();'正確嗎? – 2011-05-12 09:36:55

+0

您正在關閉表單,所以它將與表單一起處理! – V4Vendetta 2011-05-12 10:09:03

回答

0

我認爲這個問題是你要關閉在月曆包含的形式,這使得配置你的控制。

+0

這並不能解釋爲什麼它只發生在點擊「今天的日期」部分而沒有任何其他日期。 – stuartd 2011-05-12 12:54:28

1

一個有趣的問題:我能找到的唯一方法是讓窗體保持爲主窗體的屬性,並使用Hide()而不是Close()。

public partial class Form1 : Form 
    { 
     Form f = new Form(); 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void showcalendar_Click(object sender, EventArgs e) 
     { 
      ShowCalendar(); 
     } 

     void ShowCalendar() 
     { 
      DateTime current5 = DateTime.Now.AddDays(-5); 

      MonthCalendar cal = new MonthCalendar(); 
      Panel panel = new Panel(); 

      cal.MaxSelectionCount = 1; 
      cal.SetDate(current5); 
      cal.DateSelected += new DateRangeEventHandler(DateSelected); 
      cal.ShowToday = true; 
      panel.Width = cal.Width; 
      panel.Height = cal.Height; 
      panel.BorderStyle = BorderStyle.FixedSingle; 
      panel.Controls.Add(cal); 
      f.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 
      f.ShowInTaskbar = false; 
      f.Size = panel.Size; 
      f.Location = MousePosition; 
      f.StartPosition = FormStartPosition.Manual; 
      f.Controls.Add(panel); 
      f.Deactivate += delegate { f.Hide(); }; 
      f.Show(); 
     } 

     void DateSelected(object sender, DateRangeEventArgs e) 
     { 
      DateTime selection = e.Start; 
      Console.WriteLine("Selected: {0}", selection.ToLongDateString()); 

      this.Activate(); // Forces popup to de-activate 
     } 

    } 
0

有趣。我可以在這裏重現這一點(在VS 2008中運行,目標3.5)。有相當多的噪聲中的代碼,下面在這裏會導致相同的行爲,即

  • 通過單擊日/數選擇的任何日期的作品
  • 底部結果選擇「今天」區域在ObjectDisposedException

減少/最小完整的測試:

using System; 
using System.Windows.Forms; 

namespace Test 
{ 
    public class Form1 : Form 
    { 
     public Form1() 
     { 
      var dateSelectionButton = new Button(); 
      SuspendLayout(); 
      dateSelectionButton.Text = "Pick Date"; 
      dateSelectionButton.Click += (SelectDateClick); 
      Controls.Add(dateSelectionButton); 
      ResumeLayout(); 
     } 

     private void SelectDateClick(object sender, EventArgs e) 
     { 
      MonthCalendar cal = new MonthCalendar(); 
      Form f = new Form(); 
      cal.DateSelected += DateSelected; 
      f.Controls.Add(cal); 
      f.Show(); 
     } 

     void DateSelected(object sender, DateRangeEventArgs e) 
     { 
      MonthCalendar cal = (MonthCalendar)sender; 
      Form f = cal.FindForm(); 
      f.Close(); 
     } 
    } 
} 
+0

這是一個較短的repro,但它如何增加價值? – stuartd 2011-05-12 22:54:47

+0

其實我只是不明白爲什麼代碼不能這樣工作/爲什麼需要解決方法。如果沒有人能夠最終回答這個問題,我會說這可能會成爲一個可能的錯誤,而這個錯誤又需要一個小小的配方來重現它。 解決這個問題並不知道爲什麼這是必要的也是可疑的價值,imo。 – 2011-05-13 09:53:55

1

解決方法,以這樣的:從它刪除的MonthCalendar的closin之前父g承載本月MonthCalendar的表單。所以改變是添加一行cal.Parent.Controls.Remove(cal)。 DateSelected方法變爲:

void DateSelected(object sender, DateRangeEventArgs e) 
{ 
    MonthCalendar cal = (MonthCalendar)sender; 
    Form f = cal.FindForm(); 
    cal.Parent.Controls.Remove(cal); 
    f.Close(); 
} 
1

我有3個步驟的快速解決方案。

修復和增強功能:在不同版本的Windows的固定

  • 矩形動態大小。
  • 驗證主體格式是否最上層。
  • 從內存中卸載日曆形式沒有錯誤。
  • 良好行爲MonthCalendarMaskedTextBox之間控制

步驟:

1)創建一個新的Windows窗體應用程序,查看代碼在Form1並替換這一切的文字:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Globalization; 
using System.Threading; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     private System.Windows.Forms.CheckBox chkShowWeeksNumbers; 
     private System.Windows.Forms.CheckBox chkThisFormTopMost; 
     private System.Windows.Forms.MaskedTextBox maskedInputBox; 
     private System.Windows.Forms.Button btnShowFloatingCalendar; 

     public Form1() 
     { 
      this.chkShowWeeksNumbers = new System.Windows.Forms.CheckBox(); 
      this.chkThisFormTopMost = new System.Windows.Forms.CheckBox(); 
      this.maskedInputBox = new System.Windows.Forms.MaskedTextBox(); 
      this.btnShowFloatingCalendar = new System.Windows.Forms.Button(); 
      this.SuspendLayout(); 
      // 
      // chkShowNumbersOfWeeks 
      // 
      this.chkShowWeeksNumbers.AutoSize = true; 
      this.chkShowWeeksNumbers.Location = new System.Drawing.Point(18, 116); 
      this.chkShowWeeksNumbers.Name = "chkShowWeeksNumbers"; 
      this.chkShowWeeksNumbers.Size = new System.Drawing.Size(137, 17); 
      this.chkShowWeeksNumbers.TabIndex = 1; 
      this.chkShowWeeksNumbers.Text = "Show number of weeks"; 
      this.chkShowWeeksNumbers.UseVisualStyleBackColor = true; 
      // 
      // chkThisFormTopMost 
      // 
      this.chkThisFormTopMost.AutoSize = true; 
      this.chkThisFormTopMost.Location = new System.Drawing.Point(18, 139); 
      this.chkThisFormTopMost.Name = "chkThisFormTopMost"; 
      this.chkThisFormTopMost.Size = new System.Drawing.Size(124, 17); 
      this.chkThisFormTopMost.TabIndex = 2; 
      this.chkThisFormTopMost.Text = "This form TopMost"; 
      this.chkThisFormTopMost.UseVisualStyleBackColor = true; 
      this.chkThisFormTopMost.CheckedChanged += new EventHandler(chkThisFormTopMost_CheckedChanged); 
      // 
      // maskedInputBox 
      // 
      this.maskedInputBox.Location = new System.Drawing.Point(18, 53); 
      this.maskedInputBox.Mask = "00/00/0000 00:00"; 
      this.maskedInputBox.Name = "maskedInputBox"; 
      this.maskedInputBox.Size = new System.Drawing.Size(115, 20); 
      this.maskedInputBox.TabIndex = 3; 
      this.maskedInputBox.ValidatingType = typeof(System.DateTime); 
      // 
      // btnShowFloatingCalendar 
      // 
      this.btnShowFloatingCalendar.Location = new System.Drawing.Point(139, 49); 
      this.btnShowFloatingCalendar.Name = "btnShowFloatingCalendar"; 
      this.btnShowFloatingCalendar.Size = new System.Drawing.Size(65, 27); 
      this.btnShowFloatingCalendar.TabIndex = 4; 
      this.btnShowFloatingCalendar.Text = "Calendar"; 
      this.btnShowFloatingCalendar.UseVisualStyleBackColor = true; 
      this.btnShowFloatingCalendar.Click += new EventHandler(btnShowFloatingCalendar_Click); 

      // 
      // Form1 
      // 
      this.Controls.Add(this.btnShowFloatingCalendar); 
      this.Controls.Add(this.maskedInputBox); 
      this.Controls.Add(this.chkThisFormTopMost); 
      this.Controls.Add(this.chkShowWeeksNumbers); 

      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      //DateTime format using in United States 
      //More info: http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo%28v=vs.71%29.aspx 
      //   http://msdn.microsoft.com/en-us/library/5hh873ya.aspx 

      Thread.CurrentThread.CurrentCulture = new CultureInfo(0x0409); 

      CultureInfo cultureInfoUSA = new CultureInfo(0x0409, false); 
      this.maskedInputBox.Culture = cultureInfoUSA; 
     } 

     //Constructor 
     clsMonthCalendarBehavior userCalendar = new clsMonthCalendarBehavior(); 

     private void btnShowFloatingCalendar_Click(object sender, EventArgs e) 
     {   
      userCalendar.ShowCalendar(this.maskedInputBox, 
             this.chkShowWeeksNumbers.Checked, 
             this.chkThisFormTopMost.Checked); 
     } 

     private void chkThisFormTopMost_CheckedChanged(object sender, EventArgs e) 
     { 
      this.TopMost = this.chkThisFormTopMost.Checked; 
     } 
    } 
} 

2 )將新的類項目添加到項目中,並將其命名爲clsMonthCalendarBehavior.cs,稍後將其替換爲所有文本:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Drawing; 

namespace WindowsFormsApplication1 
{ 
    class clsMonthCalendarBehavior 
    { 
     private bool manualDateTimeIsDone 
     { 
      get 
      { 
       return (SetDateTimeManual(this._dateTimeInput.Text)); 
      } 
     } 

     private static DateTime dateTimeManual; 

     //Determine if the user inserting a correctly date and time 
     internal static bool SetDateTimeManual(string inputReference) 
     { 
      DateTime newDateTime = new DateTime(2000, 1, 1, 0, 0, 0); 

      bool isDateTime = DateTime.TryParse(inputReference, out newDateTime); 

      if (isDateTime) 
       dateTimeManual = newDateTime; 

      return (isDateTime ? true : false); 
     } 

     private MaskedTextBox _dateTimeInput; 

     internal void ShowCalendar(MaskedTextBox dateTimeInput, 
            bool showNumbersOfWeeks, 
            bool principalFormIsTopMost) 
     { 
      MonthCalendar monthCalendarCustomized = new MonthCalendar(); 
      Panel popupPanel = new Panel(); 
      Form floatingForm = new Form(); 

      this._dateTimeInput = dateTimeInput; 

      //OPTIONAL: Show week numbers 
      monthCalendarCustomized.ShowWeekNumbers = showNumbersOfWeeks; 
      monthCalendarCustomized.MaxSelectionCount = 1; 

      if (manualDateTimeIsDone) 
       monthCalendarCustomized.SetDate(dateTimeManual); //User, date and time selected 
      else 
       monthCalendarCustomized.SetDate(DateTime.Now); //System, actual date and time 

      monthCalendarCustomized.DateSelected += new DateRangeEventHandler(DateSelected); 
      monthCalendarCustomized.KeyDown +=new KeyEventHandler(KeyDown); 

      monthCalendarCustomized.ShowToday = true; 

      //IDEA: bolded dates about references, etc. 
      monthCalendarCustomized.BoldedDates = new DateTime[] 
      { 
       DateTime.Today.AddDays(1), 
       DateTime.Today.AddDays(2), 
       DateTime.Today.AddDays(7), 
       DateTime.Today.AddDays(31), 
       DateTime.Today.AddDays(10) 
      }; 

      popupPanel.BorderStyle = BorderStyle.FixedSingle; 

      popupPanel.Controls.Add(monthCalendarCustomized); 

      floatingForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; 
      floatingForm.ShowInTaskbar = false; 

      floatingForm.Location = Control.MousePosition; 
      floatingForm.StartPosition = FormStartPosition.Manual; 

      floatingForm.Controls.Add(popupPanel); 
      floatingForm.Deactivate += delegate { floatingForm.Close(); }; 

      //NOTE: if principal from is topmost, cannot show in front "floatingForm" with calendar 
      //  this option fix the situation. 
      floatingForm.TopMost = principalFormIsTopMost; 

      //NOTE: set initial size of controls. 
      floatingForm.Size = popupPanel.Size = new Size(20, 20); 

      floatingForm.Show(); 

      popupPanel.Size = floatingForm.Size = monthCalendarCustomized.Size; 

      popupPanel.Width = popupPanel.Width + 2; 
      popupPanel.Height = popupPanel.Height + 2; 

      floatingForm.Width = floatingForm.Width + 3; 
      floatingForm.Height = floatingForm.Height + 3; 
     } 

     void DateSelected(object sender, DateRangeEventArgs e) 
     { 
      //Set data selected with culture info mask 
      this._dateTimeInput.Text = SetTimeValue(e.Start).ToString("MM/dd/yyyy HH:mm"); 

      CloseFloatingForm(sender); 
     } 

     private static void CloseFloatingForm(object sender) 
     { 
      MonthCalendar monthCalendarCustomized = (MonthCalendar)sender; 
      Form floatingForm = monthCalendarCustomized.FindForm(); 

      monthCalendarCustomized.Parent.Controls.Remove(monthCalendarCustomized); 

      floatingForm.Close(); 
     } 

     private DateTime SetTimeValue(DateTime selectedDateTime) 
     { 
      //Recovery time of after selection, because when user select a new date 
      //Month Calendar reset the time 
      if (manualDateTimeIsDone) 
      { 
       TimeSpan addTimeValue = new TimeSpan(dateTimeManual.Hour, 
                dateTimeManual.Minute, 
                dateTimeManual.Second); 

       selectedDateTime = selectedDateTime.Add(addTimeValue); 
      } 

      return (selectedDateTime); 
     } 

     private void KeyDown(object sender, KeyEventArgs e) 
     { 
      if (e.KeyCode == Keys.Escape) 
       CloseFloatingForm(sender);     
     } 
    } 
} 

3)運行和測試。