المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : ComboBox.Items.Clear() not working -- Totally Revised Question



C# Programming
01-21-2010, 01:50 PM
My last post about this issue resulted in a lot of confusion. So I want to try this a different way:

I'm making a custom time picker that inherits directly from ComboBox. I am not using a designer to make a System.Windows.Forms.UserControl-based control. I will post the full code in a moment to clarify.

The control has a property called Increment, which is the increment in minutes between each ComboBox item. Therefore the "set" action of Increment invokes the private method RepopulateChoices(). The method is also invoked in the "set" action of another property called ShowMilitary. The first line of RepopulateChoices() is:

Items.Clear();

Remember I'm inheriting directly from ComboBox, so this syntax is CORRECT. It does not need to be prefixed by "myComboBox1." or anything like that. It is not a designer-based user control.

The problem is that I end up with duplicate items. Example: If I set Increment = 30, I'll see the items 11:00 PM, 11:30 PM, and then 12:00 AM, 12:30 AM and it keeps going. The number of duplicates depends on the nesting of containers, adding 2 days' worth of entries for every layer:

Dropped directly on a form: 96 entries (2 days @ 30 minute increments)
Dropped in a panel on a form: 192 entries (4 days)
Dropped in a panel in a TableLayout cell on a form: 288 entries (6 days)

It's like Items.Clear() is failing to do anything. I'm trying to figure out why. Here is my complete class code:


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

namespace PCA.SecureWinCtrls
{
[Description("Control for displaying a time selection combox box with custom time increments. Includes provision for PCA securiyt model."),
ToolboxBitmap(typeof(ComboBox))]
public sealed class pcaTimePicker : ComboBox
{
#region MEMBERS

///
/// Override of the base ComboBox property. Style cannot be altered due to the specific
/// use of this control.
///
[Browsable(false)]
public new ComboBoxStyle DropDownStyle
{
get
{
return ComboBoxStyle.DropDown;
}
}

///
/// Gets the current hours value. If no value is set, and exception will be thrown.
///
[Browsable(false)]
public int Hours
{
get
{
if (ShowMilitary)
return MilHours;
int i = MilHours;
if (i > 12)
return i - 12;
else if (i == 0)
return 12;
else
return i;
}
}

///
/// Gets the current hours as a military time value, regardless of display mode. If no
/// value is set, an exception will be thrown.
///
[Browsable(false)]
public int MilHours
{
get
{
ValidateValue(true);
return DateTime.Parse(Text).Hour;
}
}

///
/// Gets the current minutes value. If no value is set, and exception will be thrown.
///
[Browsable(false)]
public int Minutes
{
get
{
ValidateValue(true);
return DateTime.Parse(Text).Minute;
}
}

private bool mbMilitary = false;
///
/// Gets/sets whether the control shows time as a 24-hour clock.
///
[Description("Gets/sets whether the control shows time as a 24-hour clock."),
DefaultValue(false)]
public bool ShowMilitary
{
get { return mbMilitary; }
set
{
mbMilitary = value;
RepopulateChoices();
}
}

private int miIncrement = 30;
///
/// Gets/sets the increment of the drop-down.
///
[Description("Gets/sets the increment value in minutes. Valid values are 10 - 720."),
DefaultValue(30)]
public int Increment
{
get { return miIncrement; }
set
{
if (value < 10 || value > 720)
{
throw new Exception("Increment value must be a value in minutes ranging from 10 to 720 (12 hours).");
}
miIncrement = value;
RepopulateChoices();
}
}

#endregion

#region EVENT HANDLERS

///
/// Event fired when the control performs self-validation and fails.
///
[Description("Event fired when the control loses focus and the text value cannot be parsed as time.")]
public event EventHandler ValidationFailed;
///
/// Event fired when the control performs self-validation and succeeds.
///
public event EventHandler ValidationSucceeded;

#endregion

#region PUBLIC METHODS

///
/// Constructor.
///
public pcaTimePicker() : base()
{
base.DropDownStyle = ComboBoxStyle.DropDown;
base.Leave += new EventHandler(this_Leave);
RepopulateChoices();
}

///
/// Triggers immediate validation of the control's current value.
///
/// Indicates whether an exception should be thrown
/// if the validation fails.
public void ForceValidation(bool bCauseException)
{
ValidateValue(bCauseException);
}

#endregion

#region PRIVATE METHODS

///
/// Repopulates the combo box based on the current military and increment settings.
///
private void RepopulateChoices()
{
Items.Clear();
int i = 0;
while (i < 1440)
{
DateTime dat = new DateTime(1, 1, 1, i / 60, i % 60, 0);
if (ShowMilitary)
Items.Add(dat.ToString("HH:mm"));
else
Items.Add(dat.ToString("h:mm tt"));
i += Increment;
}
}

///
/// Checkes that the current value of the control is a parsable time.
///
private void ValidateValue(bool bOnPropertyAccess)
{
bool bOK = true;
try
{
DateTime.Parse(base.Text);
}
catch (Exception)
{
bOK = false;
if (ValidationFailed != null)
{
ValidationFailed(this, null);
if (bOnPropertyAccess)
throw;
}
else
throw;
}
if (bOK && ValidationSucceeded != null)
ValidationSucceeded(this, null);
}

#endregion

#region EVENT HANDLERS

private void this_Leave(object sender, EventArgs e)
{
ValidateValue(false);
}

#endregion
}
}