我有这个代码来创建并显示带有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函数的按钮的简单形式。
答案 0 :(得分:1)
一个有趣的问题:我能找到使其工作的唯一方法是将弹出窗体保持为Main窗体的属性,并使用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
}
}
答案 1 :(得分:1)
解决方法:在关闭承载此MonthsCalendar的表单之前,从其父级中删除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();
}
答案 2 :(得分:1)
我有3个步骤的快速解决方案。
修复和增强功能:
MonthCalendar
和MaskedTextBox
控制之间的良好行为步骤:
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)运行并测试。
答案 3 :(得分:0)
我认为问题在于您关闭了包含月份日历的表单,这会使您的控件被丢弃。
答案 4 :(得分: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();
}
}
}