|
|
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:
<br />
Items.Clear();<br />
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
[Browsable(false)]
public new ComboBoxStyle DropDownStyle
{
get
{
return ComboBoxStyle.DropDown;
}
}
[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;
}
}
[Browsable(false)]
public int MilHours
{
get
{
ValidateValue(true);
return DateTime.Parse(Text).Hour;
}
}
[Browsable(false)]
public int Minutes
{
get
{
ValidateValue(true);
return DateTime.Parse(Text).Minute;
}
}
private bool mbMilitary = false;
[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;
[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
[Description("Event fired when the control loses focus and the text value cannot be parsed as time.")]
public event EventHandler ValidationFailed;
public event EventHandler ValidationSucceeded;
#endregion
#region PUBLIC METHODS
public pcaTimePicker() : base()
{
base.DropDownStyle = ComboBoxStyle.DropDown;
base.Leave += new EventHandler(this_Leave);
RepopulateChoices();
}
public void ForceValidation(bool bCauseException)
{
ValidateValue(bCauseException);
}
#endregion
#region PRIVATE METHODS
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;
}
}
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
}
}
|
|
|
|
|
I should add that when I step-trace through RepopulateChoices() everything seems fine. When I exit the method and hit F5 to continue, my breakpoint is no longer encountered but I still end up with duplicate items. That's what is making this so darn frustrating.
|
|
|
|
|
I get your problem now. There's no way that the Items.Clear() doesn't work.
The problem might be from drawing(paint event(s)).
Ex: you drop your control on the form. The Ctor calls the RepopulateChoices.
Then the paint event is raised and ads the items once again.
Drop on a panel on a form. Form invalidate=> your control invalidate.
Panel invalidate again => your control invalidates.
That's the only reason that I could think of.
But it might not be this at all.
Do you override the OnPaint?
|
|
|
|
|
The problem are the static items in the Items property on design-time.
Just go to your form design->select a pcaTimePicker->Properties->Items delete everything in it.
After that you should not have any problems.
The problem are the following lines in the designer-file:
this.pcaTimePicker3.FormattingEnabled = true;
this.pcaTimePicker3.Items.AddRange(new object[] {
"12:00 ",
"12:30 ",
"1:00 ",
"1:30 ",
"2:00 ",
"2:30 ",
...});
this.pcaTimePicker3.Location = new System.Drawing.Point(101, 243);
this.pcaTimePicker3.Name = "pcaTimePicker3";
this.pcaTimePicker3.Size = new System.Drawing.Size(121, 21);
this.pcaTimePicker3.TabIndex = 5;
Those lines get called after your pcaTimePicker first invokes Repopulate(...).
Here some example:
public Form1()
{
InitializeComponent();
MessageBox.Show(pcaTimePicker3.Items.Count.ToString());
pcaTimePicker3.Items.Clear();
pcaTimePicker3.Increment = 30;
MessageBox.Show(pcaTimePicker3.Items.Count.ToString());
}
Hope I could help you.
Greetings
Covean
|
|
|
|
|
BRILLIANT, Covean!!! I never would have thought of looking at the designer file. That started me thinking that there has to be a way to prevent design-time population. At first I just tried adding a check against the ComboBox.DesignMode property. However, RepopulateChoices() is also called from the constructor, and DesignMode doesn't register that early. On the other hand, if I removed the call from the constructor, then nothing was populated at run-time. My final solution was:
1. Remove the call to RepopulateChoices() from the constructor.
2. Override the InitLayout method like this:
protected override void InitLayout()
{
base.InitLayout();
if (DesignMode) return;
RepopulateChoices();
}
That prevents any items from being populated at design time and still populates the ComboBox at run-time with exactly ONE set of data.
Thanks again.
|
|
|
|
|
|
And 5 for the answer seeing as OP forgot!
Dave
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn) Why are you using VB6? Do you hate yourself? (Christian Graus)
|
|
|
|
|
Thank you.
Greetings
Covean
|
|
|
|
|
if any one know then please help me ....
|
|
|
|
|
You can use the media player component to play a video. Just add it to your form and set its source as appropriate.
"WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys | Onyx
|
|
|
|
|
Thanks for your help. i done it. now i want to take a snapshot image from a video file. then tell me how can i get a snapshot image from a video file programatically?
|
|
|
|
|
I have set the form border to FixedSingle and removed the max, and min buttons but the user is still able to re size the form by double clicking on the title bar..
how can I prevent that?
|
|
|
|
|
Have you set The form's boarder style property to one of the "Fixed" enumerations (e.g. "FixedDialog")?
CCC solved so far: 2 (including a Hard One!)
37!?!! - Randall, Clerks
|
|
|
|
|
it is set to fixed single as mentioned..
is there any way to prevent resizing using winapi & c#?
|
|
|
|
|
Set the Min and Max sizes?
|
|
|
|
|
You can disable title bar double click by using this technique:
public partial class MyForm : Form
{
const Int32 HTCAPTION = 0x2;
const Int32 WM_NCLBUTTONDBLCLK = 0xA3;
protected override void WndProc(ref Message msg)
{
switch (msg.Msg)
{
case WM_NCLBUTTONDBLCLK:
if (msg.WParam.ToInt32() == HTCAPTION)
return;
break;
};
base.WndProc(ref msg);
}
}
|
|
|
|
|
That's good work. I've just created a form, fixed single without min and max buttons and it definitely doesn't maximise on double clicking the titlebar.
Regards,
Rob Philpott.
|
|
|
|
|
I want to have my form title on the left side of the title bar as usual... but I also want to have a form ID like FRM123 on the right side on the form just beside the minimize button or right most if no buttons..
how can I do that?
|
|
|
|
|
jrahma wrote: form ID like FRM123
That will be a very unprofessional thing to do
Harvey Saayman - South Africa
Software Developer
.Net, C#, SQL
you.suck = (you.Occupation == jobTitles.Programmer && you.Passion != Programming)
1000100 1101111 1100101 1110011 100000 1110100 1101000 1101001 1110011 100000 1101101 1100101 1100001 1101110 100000 1101001 1101101 100000 1100001 100000 1100111 1100101 1100101 1101011 111111
|
|
|
|
|
can I ask why?
it will be easier to identify the form specially when supporting basic users on the phone..
|
|
|
|
|
String s ="";
int? nullint = s ( How to convert "String s" to "nullable int")
|
|
|
|
|
|
First, I'd avoid nulls unless absolutly neccesary, the can cause all sorts of problems if they are not coded against.
The exact code you need depends upon your desired "failure mode" (see comment in block) but here is an answer:
static int? Convert (string value)
{
if (string.IsNullOrEmpty(value))
return null;
int returnedInt;
if (int.TryParse(value, out returnedInt))
return returnedInt;
return null;
}
also IMO nullint is a shoud be renamed as it has both "null" and "int" in it, as well as not being very descriptive.
[Edit]
Nuri Ismails post (below) achieves the same as the above, but is more compact, so I'd use that in preference.
CCC solved so far: 2 (including a Hard One!)
37!?!! - Randall, Clerks
modified on Wednesday, January 20, 2010 9:00 AM
|
|
|
|
|
How about something like this:
public int? ToNullableInt32(string s)
{
int i;
return (Int32.TryParse(s, out i)) ? i : null;
}
String s ="";
int? nullint = ToNullableInt32(s);
|
|
|
|