|
This is a general question for any other developers who have downloaded and are attempting to make use of this control. Are you having problems with it? Especially, are you having problems using it with a .NET 2.0 project?
I *appears* that the problem Glen Harvy is having is related to .NET 2.0. Though, it may also be I have failed to take some normal useage of a ComboBox into account in my code to over-draw the control to get the desired ReadOnly behavior.
In any event, I don't have VS2005; so if the problem Glen is having is related to that, I'll have to rely of those of you who do have that version to identify and fix the problem (and, one hopes, inform me of the fix).
So far in my testing and usage of this control in VS2003 (and VS2002), it has been behaving as I wanted it to.
-- modified at 9:35 Tuesday 31st October, 2006
EDIT:
The strange behavior Glen is having started with Version 1.0.004 (uploded October 12), specifically due to the code to hide the drop-down arrow when .ReadOnly and !.ReadOnlyAllowDrop
|
|
|
|
|
using System;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Contrast
{
[ToolboxItem(true)]
[ToolboxBitmapAttribute(typeof(TdhComboBox), "TdhComboBox.bmp")]
public partial class TdhComboBox : ComboBox
{
private bool _ReadOnly = false;
private Win32_Hover.ComboBoxInfo _CboInfo;
private byte _Suppress = 0;
private EditBox_InterceptWindowMessages _nwEdit;
private ListBox_InterceptWindowMessages _nwList;
#region Constructor and Dispose
public TdhComboBox()
{
_CboInfo = new Win32_Hover.ComboBoxInfo();
_CboInfo.cbSize = Marshal.SizeOf(_CboInfo);
_nwEdit = new EditBox_InterceptWindowMessages(this);
_nwList = new ListBox_InterceptWindowMessages(this);
}
#endregion
#region Override Methods
protected override void OnHandleCreated(EventArgs args)
{
base.OnHandleCreated(args);
Win32_Hover.GetComboBoxInfo(this.Handle, ref _CboInfo);
if (this._ReadOnly)
{
if (this.DropDownStyle != ComboBoxStyle.DropDownList)
{
_nwEdit.AssignHandle(_CboInfo.hwndEdit);
}
_nwList.AssignHandle(_CboInfo.hwndList);
}
Colors_Set();
}
protected override void OnHandleDestroyed(EventArgs args)
{
base.OnHandleDestroyed(args);
if (this._Suppress > 0)
{
if (this.DropDownStyle != ComboBoxStyle.DropDownList)
{
_nwEdit.ReleaseHandle();
}
_nwList.ReleaseHandle();
}
}
protected override void OnSelectionChangeCommitted(EventArgs e)
{
if (!this._ReadOnly)
{
base.OnSelectionChangeCommitted(e);
}
}
#endregion
#region Novel Properties
[Category("Behavior")]
[Description("Determines whether the text in the edit control can be changed.")]
[DefaultValue(typeof(bool), "false")]
public bool ReadOnly
{
get { return this._ReadOnly; }
set
{
if (this._ReadOnly != value)
{
this._ReadOnly = value;
if (this.IsHandleCreated)
{
string s = this.Text;
this.RecreateHandle();
this.Text = s;
}
}
}
}
[Browsable(false)]
internal Win32_Hover.ComboBoxInfo CboInfo
{
get { return this._CboInfo; }
}
[Browsable(false)]
internal byte Suppress
{
get { return this._Suppress; }
set { this._Suppress = value; }
}
#endregion
#region Novel Methods
public void Colors_Set()
{
if (_CboInfo.hwndEdit != IntPtr.Zero)
{
byte val;
val = (byte)(this._ReadOnly ? 1 : 0);
Win32_Hover.SendMessage(_CboInfo.hwndEdit, Win32_Hover.EM_SETREADONLY, val, 0);
this._Suppress = val;
}
}
#endregion
#region Hover logic: protected override void WndProc(ref System.Windows.Forms.Message message)
protected override void WndProc(ref System.Windows.Forms.Message msg)
{
bool discardMessage = false;
if (this.ReadOnly)
{
switch (msg.Msg)
{
case Win32_Hover.WM_LBUTTONDBLCLK:
case Win32_Hover.WM_LBUTTONDOWN:
if (this.DropDownStyle == ComboBoxStyle.DropDown)
{
int X, Y;
X = (int)msg.LParam << 16 >> 16;
Y = (int)msg.LParam >> 16;
Win32_Hover.RECT r = this.CboInfo.rcButton;
if (X >= r.left && Y >= r.top && X < r.right && Y < r.bottom)
{
this.Suppress = 5;
}
}
break;
case Win32_Hover.WM_UNDO:
if (this.DropDownStyle == ComboBoxStyle.DropDownList)
{
discardMessage = true;
}
break;
case Win32_Hover.WM_KEYDOWN:
switch ((Keys)msg.WParam)
{
case Keys.Delete:
if (this.DropDownStyle == ComboBoxStyle.DropDownList)
{
if (this.AutoCompleteMode != AutoCompleteMode.None
&& this.AutoCompleteSource != AutoCompleteSource.None
)
{
discardMessage = true;
}
}
break;
default:
break;
}
break;
case Win32_Hover.WM_CHAR:
case Win32_Hover.WM_DEADCHAR:
case Win32_Hover.WM_UNICHAR:
switch ((Keys)msg.WParam)
{
case Keys.Return:
case Keys.Escape:
case Keys.Space:
break;
default:
if (this.DropDownStyle == ComboBoxStyle.DropDownList)
{
if (this.AutoCompleteMode != AutoCompleteMode.None
&& this.AutoCompleteSource != AutoCompleteSource.None
)
{
discardMessage = true;
}
}
break;
}
break;
case Win32_Hover.WM_PAINT:
if (this.DropDownStyle == ComboBoxStyle.DropDownList)
{
if (this.Enabled && (this.DroppedDown || !this.Focused))
{
base.WndProc(ref msg);
Graphics g = this.CreateGraphics();
Win32_Hover.RECT r = this.CboInfo.rcItem;
RectangleF f = new RectangleF(r.left, r.top, r.right - r.left, r.bottom - r.top);
g.FillRectangle(SystemBrushes.Control, f);
g.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), f);
g.Dispose();
discardMessage = true;
}
}
break;
default:
break;
}
}
if (discardMessage)
{
}
else
{
base.WndProc(ref msg);
}
}
#endregion
}
#region Class: TdhComboBox_NativeWindow : System.Windows.Forms.NativeWindow
internal class EditBox_InterceptWindowMessages : NativeWindow
{
private TdhComboBox _parentComboBox;
#region Class Constructor: public TdhComboBox_NativeWindow(xboXComboBox parentComboBox, NativeWindowType nwType, IntPtr hwnd)
public EditBox_InterceptWindowMessages(TdhComboBox parentComboBox)
{
_parentComboBox = parentComboBox;
}
#endregion
#region protected override void WndProc(ref System.Windows.Forms.Message message)
protected override void WndProc(ref Message msg)
{
bool discardMessage = false;
if (_parentComboBox.ReadOnly)
{
switch (msg.Msg)
{
case Win32_Hover.WM_UNDO:
discardMessage = true;
break;
case Win32_Hover.WM_KEYDOWN:
switch ((Keys)msg.WParam)
{
case Keys.Return:
if (_parentComboBox.DropDownStyle == ComboBoxStyle.Simple)
{
if (_parentComboBox.AutoCompleteMode != AutoCompleteMode.None
&& _parentComboBox.AutoCompleteSource != AutoCompleteSource.None
)
{
if (_parentComboBox.FindStringExact(_parentComboBox.Text) == -1)
{
_parentComboBox.Suppress = 2;
}
}
}
break;
default:
break;
}
break;
case Win32_Hover.WM_SYSKEYDOWN:
switch ((Keys)msg.WParam)
{
case Keys.Return:
if (_parentComboBox.DropDownStyle == ComboBoxStyle.Simple)
{
if (_parentComboBox.AutoCompleteMode != AutoCompleteMode.None
&& _parentComboBox.AutoCompleteSource != AutoCompleteSource.None
)
{
if (_parentComboBox.FindStringExact(_parentComboBox.Text) == -1)
{
_parentComboBox.Suppress = 2;
}
}
}
break;
default:
break;
}
break;
case Win32_Hover.WM_CHAR:
case Win32_Hover.WM_DEADCHAR:
case Win32_Hover.WM_UNICHAR:
break;
case Win32_Hover.WM_SETTEXT:
if (_parentComboBox.Suppress > 1)
{
_parentComboBox.Suppress--;
discardMessage = true;
}
break;
default:
break;
}
}
if (discardMessage)
{
}
else
{
base.WndProc(ref msg);
}
}
#endregion
}
#endregion
#region Class: TdhComboBox_NativeWindow : System.Windows.Forms.NativeWindow
internal class ListBox_InterceptWindowMessages : NativeWindow
{
private TdhComboBox _parentComboBox;
#region Class Constructor: public TdhComboBox_NativeWindow(xboXComboBox parentComboBox, NativeWindowType nwType, IntPtr hwnd)
public ListBox_InterceptWindowMessages(TdhComboBox parentComboBox)
{
_parentComboBox = parentComboBox;
}
#endregion
#region protected override void WndProc(ref System.Windows.Forms.Message message)
protected override void WndProc(ref Message msg)
{
bool discardMessage = false;
if (_parentComboBox.ReadOnly)
{
switch (msg.Msg)
{
case Win32_Hover.WM_LBUTTONDOWN:
case Win32_Hover.WM_LBUTTONDBLCLK:
{
int tmpX, tmpY, spread, X, Y;
calcSpread(out tmpX, out tmpY, out spread);
X = (int)msg.LParam << 16 >> 16;
Y = (int)msg.LParam >> 16;
if (_parentComboBox.DropDownStyle == ComboBoxStyle.DropDown)
{
_parentComboBox.Suppress = 2;
}
if (X >= 0 && Y >= 0 && X < tmpX - 1 && Y < tmpY)
{
discardMessage = true;
}
}
break;
case Win32_Hover.WM_LBUTTONUP:
if (_parentComboBox.DropDownStyle != ComboBoxStyle.Simple)
{
_parentComboBox.DroppedDown = false;
}
break;
case Win32_Hover.WM_RBUTTONUP:
if (_parentComboBox.DropDownStyle != ComboBoxStyle.Simple)
{
int tmpX, tmpY, spread, X, Y;
calcSpread(out tmpX, out tmpY, out spread);
X = (int)msg.LParam << 16 >> 16;
Y = (int)msg.LParam >> 16;
if (X >= tmpX - 2 && Y >= 0 && X < spread - 2 && Y < tmpY)
{
if (_parentComboBox.DropDownStyle == ComboBoxStyle.DropDown)
{
_parentComboBox.Suppress = 2;
}
_parentComboBox.DroppedDown = false;
discardMessage = true;
}
}
break;
case Win32_Hover.WM_MOUSEMOVE:
if (_parentComboBox.DropDownStyle != ComboBoxStyle.Simple)
{
int tmpX, tmpY, spread, X, Y;
calcSpread(out tmpX, out tmpY, out spread);
X = (int)msg.LParam << 16 >> 16;
Y = (int)msg.LParam >> 16;
if (X >= 0 && Y >= 0 && X < tmpX - 2 && Y < tmpY)
{
discardMessage = true;
}
}
break;
case Win32_Hover.LB_SETCURSEL:
if (_parentComboBox.Suppress > 1)
{
_parentComboBox.Suppress--;
discardMessage = true;
}
break;
case Win32_Hover.WM_KEYDOWN:
switch ((Keys)msg.WParam)
{
case Keys.Up:
case Keys.Down:
case Keys.PageUp:
case Keys.PageDown:
discardMessage = true;
break;
case Keys.Left:
case Keys.Right:
case Keys.Home:
case Keys.End:
if (_parentComboBox.DropDownStyle == ComboBoxStyle.DropDownList)
{
discardMessage = true;
}
break;
case Keys.F4:
if (_parentComboBox.DropDownStyle == ComboBoxStyle.DropDown)
{
_parentComboBox.Suppress = (byte)(_parentComboBox.DroppedDown ? 2 : 3);
}
break;
default:
break;
}
break;
case Win32_Hover.WM_CHAR:
case Win32_Hover.WM_DEADCHAR:
case Win32_Hover.WM_UNICHAR:
switch ((Keys)msg.WParam)
{
case Keys.Back:
case Keys.Return:
case Keys.Escape:
case Keys.Space:
break;
default:
if (_parentComboBox.DropDownStyle == ComboBoxStyle.DropDownList)
{
discardMessage = true;
}
break;
}
break;
default:
break;
}
}
if (discardMessage)
{
}
else
{
base.WndProc(ref msg);
}
}
#endregion
private void calcSpread(out int tmpX, out int tmpY, out int spread)
{
if (_parentComboBox.DropDownStyle == ComboBoxStyle.Simple)
{
spread = _parentComboBox.Width;
Win32_Hover.RECT r = _parentComboBox.CboInfo.rcItem;
if (_parentComboBox.IntegralHeight)
{
tmpY = (_parentComboBox.Height - r.bottom - r.top) / _parentComboBox.ItemHeight * _parentComboBox.ItemHeight;
}
else
{
tmpY = _parentComboBox.Height - r.bottom - r.top;
}
}
else
{
spread = Math.Max(_parentComboBox.Width, _parentComboBox.DropDownWidth);
if (_parentComboBox.IntegralHeight)
{
tmpY = _parentComboBox.MaxDropDownItems * _parentComboBox.ItemHeight;
}
else
{
tmpY = _parentComboBox.DropDownHeight;
}
}
if (_parentComboBox.Items.Count > tmpY / _parentComboBox.ItemHeight)
{
tmpX = spread - SystemInformation.VerticalScrollBarWidth;
}
else
{
tmpX = spread;
}
}
}
#endregion
#region Class: Win32_Hover
internal class Win32_Hover
{
[DllImport("user32.dll")]
internal static extern bool GetComboBoxInfo(IntPtr hwndCombo, ref ComboBoxInfo info);
[DllImport("user32.dll")]
internal static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
internal const int EM_SETREADONLY = 0x00CF;
internal const int WM_LBUTTONDOWN = 0x0201;
internal const int WM_LBUTTONDBLCLK = 0x0203;
internal const int WM_LBUTTONUP = 0x0202;
internal const int WM_RBUTTONDOWN = 0x0204;
internal const int WM_RBUTTONUP = 0x0205;
internal const int WM_MOUSEMOVE = 0x0200;
internal const int LB_SETCURSEL = 0x0186;
internal const int WM_UNDO = 0x0304;
internal const int WM_KEYDOWN = 0x0100;
internal const int WM_SYSKEYDOWN = 0x0104;
internal const int WM_CHAR = 0x0102;
internal const int WM_DEADCHAR = 0x0103;
internal const int WM_UNICHAR = 0x0109;
internal const int WM_SETTEXT = 0x000c;
internal const int WM_PAINT = 0x000F;
[StructLayout(LayoutKind.Sequential)]
internal struct ComboBoxInfo
{
public int cbSize;
public RECT rcItem;
public RECT rcButton;
public int stateButton;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
}
#endregion
}
|
|
|
|
|
Thanks for your comment.
When I get some time, I'll look at this more closely;
you may have good ideas I can incorporate into my control,
or learn from, even if I don't include them in the control.
However, I must point out that one of the things you've
simplified out is the visual change to the control when it
has been set to ReadOnly -- and that was the whole point!
Still, if your version does what you want for your apps,
then there is certainly no reason for you not to simplify
it.
|
|
|
|
|
This program is designed for use with Microsoft .NET Framework 2.0 or newer (newer version of .NET may contain features that break the ReadOnly functionality). Some mode of ComboBox may not be supported (Please tell me if you find the mode...). The mode Control.CheckForIllegalCrossThreadCalls == false for ComboBox or its container (including Form, GroupBox...) is surely NOT supported!
|
|
|
|
|
|
I have downloaded it but not able to use it..
I am opening the demo with VS2005 also converting it.
Its giving me build errors.
Please help..
Thanks in advance
Raj Sharma
|
|
|
|
|
Thanks for the new feature - it is worth the effort
BUT -
When ReadOnly is True and ReadOnlyAllowDrop is False (which is what I need) the contents of the combobox does not always show the contents. I have 12 comboboxes on one page and some of them do and some don't. When it does show the name - moving the mouse over the contents will blank it out and the arrow appears.
Seems to work OK when both are True though.
Glen Harvy
|
|
|
|
|
I'm out of town for the weekend, so I can't look into the problem right now.
I suspect that the problem is going to be related to the difference between the DropDownStyles DropDown and a DropDownList.
Could you check to seen whether the DropDownStyle is the commonality to the odd behavior you're experiencing? Thanks.
|
|
|
|
|
There are 13 comboboxes. There are 9 type A and 4 type B. All types are configured the same except Type A is a lookupbox configuration whilst Type B is a simple select from a hardcoded list. Type A therefor have databindings to the SelectedValue whilst Type B have a databinding to the TextValue.
Initially both Types have their Readonly set True, all are DropDownList.
On loading the form:
No comboboxes have any text content visible.
All comboboxes have drop down arrows.
Move through the recordset:
Type A have text and no drop down arrow (however the top horizontal pixels of the drop down arrow are visible). Move mouse over text and text disappears and arrow appears.
Type B do not change ie. no text with drop downs visible.
Toggle Readonly for editing:
Type A and Type B appear with text and drop down arrows and work as expected.
Toggle Readonly to save edit:
Revert to behaviour as in Loading the form above.
Have a good weekend and try not to think about it (bet ya can't!).
-- modified at 2:19 Sunday 15th October, 2006
Glen Harvy
|
|
|
|
|
I haven't been able to duplicate the problems you're experiencing. Clearly, I'm not doing the right thing to cause the error in my testing -- could you send me some sample code illustrating how you're populating/loading and using the control? My email address is: ilion7@hotmail.com
When I was writing the code for this functionality, the problem I had was in getting the text and drop-down arrow to work properly when (DropDownStyle == DropDown). When (DropDownStyle == DropDownList), it practically took care of itself.
As for the visibility of the top horizontal pixels of the drop-down arrow, I know what that was. This code was originally written to draw the .Items in the DropList, so it created one Rectangle which was used for both painting the background and painting the text. When I was modifying the code for this function, at first I was creating a larger Rectangle, but that caused the text to "jump" when switching modes. Due to the system colors on this machine (Win2000), that line of pixels wasn't visibly apparent to me, so that small error made it into the code and .dll I uploaded.
I've solved that (minor) problem by creating separate Rectangles for drawing the backgroung and text.
But, as for the major problem my code is causing you, until I can duplicate it, I don't know what to do. I can think of some things which *might* help (for instance, it may well be that I need to override the OnPaint() method, or it may be that I need to specially process the WM_PAINT message in WndProc() for both DropDownStyles), but I'd prefer to be able to test with some degree of confidence that I've resolved it.
The text is probably vanishing due to the way I'm setting (or, not setting, as the case may be) the string variable 'itemText,' which is used in drawing the text. If so, that should be easy to fix.
|
|
|
|
|
Glen,
Did the new code I emailed you solve the problem you're having?
Since I don't have VS2005, I'm having to guess both at what exactly the problem is and what exactly might resolve it.
|
|
|
|
|
Never got it - I've been waiting to hear back from you
I'm using your original version at the moment.
I sent you the 2005 compiled .dll of 1.004 and I presume you got that email. BTW Did I tell you I also compiled the 1.004 version in 2003 with the same results as the 2005 compile?
Send me you new one again and I'll have a look at it straight away.
Cheers,
Glen Harvy
|
|
|
|
|
"Never got it"
I suspected that, which is why I posted a note here.
"I sent you the 2005 compiled .dll of 1.004 and I presume you got that email. "
I received it, but what I need to see is code so I can try to follow what's happening as it executes. From what you'd said earlier, I was speculating that you might be using the control differently that I've ever thought of using it.
"BTW Did I tell you I also compiled the 1.004 version in 2003 with the same results as the 2005 compile?"
No, you didn't mention that. Knowing this may help me duplicate the condition in testing -- I've been using the control in my own VS2003 project (the one I'm actually being paid to write), and it has been working as I expect it to work. However, I'm making use of the .DLL I complied under VS2002.
Perhaps that is the key here; perpaps there is something different about the Windows messages or the order/execution of events between VS2002 and the newer versions.
"Send me you new one again and I'll have a look at it straight away."
I've sent it again. Let's hope that this time you get it.
EDIT: I made a copy of the TdhComboBox project and its demo project and converted them to VS2003. So far, I haven't seen the problem you're having. But then, the version I'm now using is built from the source-code version I sent you a few minutes ago, rather than the source-code version you currently have.
-- modified at 12:02 Thursday 26th October, 2006
|
|
|
|
|
I received the email you sent today (Fri, Oct 27), but when I try to send you new source code, my email bounces back as undeliverable -- I just happened to check the "Junk Mail" folder, which is where HotMail decided to put the notification. I suppose that's what happened previously.
Please add the following method to the control's code (into the version I sent you yesterday). I'd mentioned when I was able to get an email through to you that I suspected I'd need to implement/override the OnPaint() method. I hope this will solve the problem you're having.
protected override void OnPaint(System.Windows.Forms.PaintEventArgs pevent)
{
base.OnPaint(pevent);
#region (Optionally) Over-Paint the control's "drop-arrow"
if( this.Enabled
&& (this._ReadOnly && !this._ReadOnlyAllowDrop)
&& (this.DropDownStyle != System.Windows.Forms.ComboBoxStyle.Simple)
)
{
System.Windows.Forms.DrawItemEventArgs argsDraw = new
System.Windows.Forms.DrawItemEventArgs(
null, this.Font, System.Drawing.Rectangle.Empty, -1,
System.Windows.Forms.DrawItemState.None,
Colors_Get_ForeColor(), Colors_Get_BackColor() );
OnDrawItem(argsDraw);
}
#endregion
}
|
|
|
|
|
Ilíon wrote: I received the email you sent today (Fri, Oct 27), but when I try to send you new source code, my email bounces back as undeliverable
My ISP decided to play around with some settings so I have had to change hosting.
If you can't reach glen@aquarius.com.au could you send it to glenharvy@hotmail.com instead.
Thanks.
Glen Harvy
|
|
|
|
|
Hi,
I've been implementing a ComboBox that combines several ideas from the Code Project (NullableComboBox, width of drop down set based on text width, ability to get/format text based on more than one column etc)
Your article inspired me to add in ReadOnly - I also didn't like not having it but didn't think about adding it myself - doh.
Anyway I noticed that there's a much easier way of getting the text in OnDrawItem() - a ListControl has a GetItemText() method you can use.
Your Code:
#region Determine the string(text) to .Draw<br />
string itemText = "";<br />
if( (args.Index >= 0) && (args.Index < this.Items.Count) )<br />
{<br />
if (this.DataSource != null)<br />
{<br />
if (DisplayMember.Length > 0)
{
System.Data.DataRowView drv = (System.Data.DataRowView)this.Items[args.Index];
itemText = drv[this.DisplayMember].ToString();
}
}<br />
else<br />
{<br />
itemText = this.Items[args.Index].ToString();<br />
}<br />
}<br />
else<br />
if ((args.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit)
{<br />
itemText = this.Text;
}<br />
#endregion
becomes:
#region Determine the string(text) to .Draw<br />
string itemText = "";<br />
if( (args.Index >= 0) && (args.Index < this.Items.Count) )<br />
itemText = GetItemText(this.Items[args.Index]);<br />
#endregion
Cheers,
Alan.
|
|
|
|
|
"Anyway I noticed that there's a much easier way of getting the text in OnDrawItem() - a ListControl has a GetItemText() method you can use ... "
Thank you, that is a good suggestion.
"I've been implementing a ComboBox that combines several ideas from the Code Project (NullableComboBox, width of drop down set based on text width, ability to get/format text based on more than one column etc)"
I have a "multi-column" ComboBox (which is based on an article from CodeProject[^]) -- one of these days I need to submit an article for it, since my code extends the original code in interesting ways. Though, on the other hand, a quick search just now shows newer projects than that I started with; it may be that my code is obsolete.
Anyway, when you say "... ability to get/format text based on more than one column ..." that sounds to me as though you mean something different from a multi-column display in the DropList. Have you submitted an article on your control? I'd like to see what you've done.
-- modified at 10:28 Tuesday 10th October, 2006
|
|
|
|
|
Ilíon wrote: Anyway, when you say "... ability to get/format text based on more than one column ..." that sounds to me as though you mean something different from a multi-column display in the DropList
You're right I mean that I have situations where I want the displayed text to be taken from more than one column of the DataRow or wherever. eg FirstName and LastName. The only way I've found to do this is to override DrawItem and provide a delegate GetDisplayString that calls back to get the correctly formatted text.
So instead of setting DisplayMember to FullName and having a "Concatanated column" - sorry I forget the SQL name for it - that is created in the select statement. I can supply a call back function that correctly formats the text.
To give you another example that I couldn't think how to do any other way I have a program that uses CustomerID as the primary key, but this isn't always easy to remember so I origionaly used CompanyName as the DisplayString. Now however I have a GetCompanyDisplayString call back function that returns a string in the format "CustomerID (CompanyName)".
I've not put much polish on my control and I don't think it works properly except when DropDownStyle is set to DropDownList - since all my ComboBoxes are used to limit user input to a predefined set of options I've always set this anyway.
I'll think about putting up an article when I get some spare time, but I hadn't so far because I was mainly just amalgamating other articles from CP
Cheers,
Alan
|
|
|
|
|
I uploaded a new version incorporating your suggestion.
|
|
|
|
|
Great work - has made life much easier
Glen Harvy
|
|
|
|
|
All through my professional career it has been one of the small pleasures of life to find ways to help my co-workers do their jobs easier/better. If now, via CodeProject, I may occasionally help people I've never met do their jobs easier/better, so much the better.
The version I uploaded yesterday has a new (minor) feature you may like: the control now hides the "drop-arrow" when it is in ReadOnly mode and the .ReadOnlyAllowDrop property is false. This feature is eye-candy, I suppose, but sometimes eye-candy is important.
|
|
|
|
|
Hi,
your control is cool;), but it has little error => Select you combobox and press Alt + arrow down. Combobox shows dropdownlist which has gray backcolor. And then move mouse cursor over dropdownlist and select another item. Then press tab key. After that SelectedItem is new item .
Can you fix this error. Sorry for my english.
Regards,
Beda
|
|
|
|
|
Thank you for your feedback. The error you've noticed is related (though not exactly the same) as the problem Patric noticed.
I've already fixed this, though I haven't yet posted it (Can you believe it? Actually doing the work the boss needs takes precidence!?). I hope to get the new version posted today.
I've had these problems fixed for a few days now. My delay in getting the fix uploaded to CodeProject is because I wanted to incorporate Patric's suggestion of enabling the DropList (as a non-selectable list) while the control is in read-only mode.
|
|
|
|
|
Thank you for your answer. I'll wait for new version because it will help me.
It makes me crazy when combobox, checkbox and datetimepicker don't have readonly property and my customers demand it.
Thank you for you work.;)
Regards,
Beda
|
|
|
|
|
I've uploaded the new version. Enjoy.
|
|
|
|
|