2011-05-12 80 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)运行和测试。