|
Hi IssaharNoam
Hey thanks for replying!
I had a DGV which has as one of the columns a slightly modified version of your very good code. When a user selects from the drop down the displayed value shows and attached to that is a valuemember which the user never sees. However, if you, upon loading the form actually load the display member into a cell there is no associated value member. When you use
dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString());
and the value was added programmatically you only get the displaymember. I needed the associated the valuemember which is not existent for those rows that were added by the program. In the end I added a hidden column and forced the value member to be added there. This ensured I always had the associated value member of that column even if the column didnt have it.
I would like to take this opportunity to thank you for your article. I am a beginner at this and I was quite surprised to find they never added the option for multi columns in comboboxes.
Kind Regards
Simon
|
|
|
|
|
Hi, Simon!
Sorry, I didn't understand again
I use the following code to update the value:
dataGridView1.Rows[e.RowIndex].Cells[2].Value = 1;
As I result, the grid cell displayed text changes automatically.
If I want to know which text is displayed I call for following code
dataGridView1.Rows[e.RowIndex].Cells[2].FormattedValue.ToString()
As a advice, if you writing commercial application - buy third part controls, they are much more boosted than standard MS pack. You will spend so much time to try to force MS controls to work like you want to.
E.g. Janusys or DotNetBar pack gives you easy multicolumn combobox option. It deserves to spend some dollars...
Thanks
Issahar
|
|
|
|
|
Hi IssaharNoam,
I am facing a problem that I want to get two values from the selected list in MultiColumnCombobox and fill the next cell with 2nd value.Please suggest me how is it possible.
Thanks In Advance
Pankaj Rai
|
|
|
|
|
Hi!
If I understood your question, you mean that you want to get the second column values in the multicolumn combobox.
If yes, you cannot get it from it because this combobox control doesn't really contain all the columns, the trick I do is just painting the combobox datasource values inside the combobox ownerdraw rows.
But you can do is:
1. check which value will be selected in the combobox (CellEndEdit event)
2. go to the datasource of this specific column
in my sample is:
newColumn.DataSource = ds.LogMessageTypes;
3. Query this datasource by yourself the relevant value by using the key you have got from combobox value
in my sample it would something like:
int typeId =
string query = string.Format("{0}={1}",ds.LogMessageTypes.TypeIdColumn.ColumnName, typeId);
DataRow[] rows = ds.LogMessageTypes.Select(query)
if(rows.length>0)
{
}
Hope it helps
Issahar
|
|
|
|
|
Hello, Isshar!
this article was really helped me alot in coding n time also
very thanks
a small requirement:
am displaying two columns in multicolumncombobox as
newColumn.DataPropertyName = Sds.Tables[0].Columns[0].ColumnName;<br />
newColumn.DisplayMember = Sds.Tables[0].Columns[0].ColumnName;<br />
newColumn.ValueMember = Sds.Tables[0].Columns[1].ColumnName;
in some other datagridview events i want to retrieve these two values
based on the section of that combobox value i have to fill the remaining cell values to that perticular row.
i wrote code in dataGridView1_CellClick event
{
if (e.ColumnIndex == 1)
{
int rowNo = e.RowIndex;
string prId = dataGridView1.Rows[rowNo].Cells[1].Value.ToString();
based on prId am retrieving values and filling remaining cells to that row.
}
}
but the problem is
1) it is not filling the remaining cells at the time of selecting that perticular comboboxcolumn
2)If i leave that cell and comeagain to that cell then remaining cells were filling
i tried in cell Leave event and cellValuechanged event also but no use
am sure that i am calling this in some wrong event which is not suitable to this requirement
can anybody shed some light on this
on which Datagridview event i have to call this to effect that row based on the selection of cell(comboboxColumn cell)
how can i do this???
please reply me
Thankyou very much once again
--Naren
modified on Tuesday, December 1, 2009 6:39 AM
|
|
|
|
|
Hi!
My owner draw code contains GDI leaks
Please be aware to dispose all the Brushes/Pens that are allocated in the paiting event code.
I will try to fix that in my demo soon
Thanks
Issahar
|
|
|
|
|
This control is wonderful. However in my case I needed to use IList as DataSource.
Although I have found a working solution but am not very satisfied with it. WIll be working more on it. Is there anyone facing the same problem? or may be author would like to enhance the control.
Here is my implementation of in OnDrawItem of DataGridViewMultiColumnComboEditingControl
if(currentRow!=null)
{
}
else
{
string currentText = GetItemText(Items[e.Index]);
SolidBrush normalBack = new SolidBrush(Color.White);
e.Graphics.FillRectangle(normalBack, rec);
if (DroppedDown && !(Margin.Top == rec.Top))
{
Type objectType = objCurrentItem.GetType();
PropertyInfo propertyDisplay = objectType.GetProperty(this.DisplayMember);
PropertyInfo propertyValue = objectType.GetProperty(this.ValueMember);
PropertyInfo[] properties = new PropertyInfo[] { propertyValue, propertyDisplay };
int currentOffset = rec.Left;
SolidBrush HightlightedBack = new SolidBrush(System.Drawing.SystemColors.Highlight);
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e.Graphics.FillRectangle(HightlightedBack, rec);
}
bool addBorder = false;
foreach (PropertyInfo p in properties)
{
string value = p.GetValue(objCurrentItem, null).ToString();
if (addBorder)
{
SolidBrush gridBrush = new SolidBrush(Color.Gray);
long linesNum = lineWidth;
while (linesNum > 0)
{
linesNum--;
Point first = new Point(rec.Left + currentOffset, rec.Top);
Point last = new Point(rec.Left + currentOffset, rec.Bottom);
e.Graphics.DrawLine(new Pen(gridBrush), first, last);
currentOffset++;
}
}
else
{
addBorder = true;
}
SizeF extent = e.Graphics.MeasureString(value, e.Font);
decimal width = (decimal)extent.Width;
Rectangle textRec = new Rectangle(currentOffset, rec.Y, (int)decimal.Ceiling(width), rec.Height);
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
SolidBrush HightlightedText = new SolidBrush(System.Drawing.SystemColors.HighlightText);
e.Graphics.FillRectangle(HightlightedBack, currentOffset, rec.Y, fixedAlignColumnSize, extent.Height);
e.Graphics.DrawString(value, e.Font, HightlightedText, textRec);
}
else
{
e.Graphics.FillRectangle(normalBack, currentOffset, rec.Y, fixedAlignColumnSize, extent.Height);
e.Graphics.DrawString(value, e.Font, NormalText, textRec);
}
currentOffset += fixedAlignColumnSize;
}
}
else
{
e.Graphics.DrawString(currentText, e.Font, NormalText, rec);
}
}
|
|
|
|
|
I am useing VB2005. In my application I have added one unbound datagridview. I have added one combox cell with some values like "America","Australia","India","Indonesia" etc. Now I want when the user press any key on the combobox, the nearest matches will be shown by droping down. For example if the user press "A or a", the combobox cell will show both "America","Australia". Please help me by providing the code.
|
|
|
|
|
Hi!
I didn't understand from your question if this is in scope of my sample or not.
Anyway, if I understood you good, you mean you want auto complete features in your DataGridView combo cell.
I think the following forum discussing can help you:
http://www.codeguru.com/FORUM/showthread.php?t=404089[^]
I hope it helps you
Issahar
|
|
|
|
|
Great job and very useful. Is there a way to display the column headers on the combobox? I know how to do this when extending the combo box but here you have extended the datagridviewComboBoxColumn.
maryjo
|
|
|
|
|
Hello, Maryjo!
Thanks for compliments
I didn't think about that in this solution.
I used the item owner draw so I didn't redraw the whole combobox but only items
May be the add first item the will be empty and redraw it in owver draw as titles? I think it may work but it is a little bit ugly solution
IssaharNoam
|
|
|
|
|
I have struggled to find code that works. I saw yours, and am trying it. But it seems that when I select an item from the mult-column drop down list, it automatically sorts. I don't want it to.
Also, if I select an item from the multi-column drop down list, and then immediately select an item from the row below, it errors out.
My two questions?
1. How to prevent auto sorting?
2. How to prevent error when selecting first row, then item on second row.
thanks,
arevans
|
|
|
|
|
Sorry for delay in my response. I uploaded now fixed version that working much better, you invited to try
Issahar
|
|
|
|
|
Hello Issahar:
Thanks for sharing your approach.
I want to use your control to display all the combobox items in a datagridview cell with only one row.
My datagridview will permit to the user to add rows on demand, and we need to show all the items in the combobox.
Right now the combobox only show the items that are being displayed on the datagridview.
Appreciate your help to achieve that.
Thanks in advance
David
|
|
|
|
|
I uploaded now fixed version that working much better, you invited to try
It give the solution for your question
Issahar
|
|
|
|
|
Has anyone taken this code and fleshed out this control a bit more?
If so, can I please see your source code?
|
|
|
|
|
|
I uploaded now fixed version that working much better, you invited to try
Issahar
|
|
|
|
|
Hello Issahar,
Can you please help me with the multiline combobox issue?
I would be pleased if you can send me some sample code to my email kaandemirtas@gmail.com
Thanks in advance.
Best regards,
Kaan Demirtas
Istanbul-TURKEY
|
|
|
|
|
I uploaded now fixed version that working much better, you invited to try
Issahar
|
|
|
|
|
I've tried so hard for a whole day that I still cannot get through this tough problem, somebody please, help me!
I've got the code for Multi Column Combo in DataGridView to solve the problem of displaying multiple data, but I got stuck in displaying some values. Everything goes just fine, but when I tried to display values with the key value diplicated, it doesn't work. For example, I intended to display two rows "bmx2100 |23455 |34" and "bmx2100 |11111 |100", they have the same attribute "bmx2100", but the primary key "23455" and "11111" are different. That was what suppose to be, but now, the program displayed "bmx2100 |23455 |34" twice, and during DEBUG, I print out all the temporary variables and I found that they are all correct! So, what would be the problem!?
This is the Multi Column Combo Cell : http://www.codeproject.com/useritems/Multi_Column_Combo_Cell.asp
And this is the code snippet I modified:
protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)<br />
{<br />
Rectangle rec = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);<br />
DataGridViewMultiColumnComboColumn column = ownerCell.OwningColumn as DataGridViewMultiColumnComboColumn;<br />
DataTable valuesTbl = column.valuesTbl;<br />
string joinByField = column.joinFieldName;<br />
SolidBrush NormalText = new SolidBrush(System.Drawing.SystemColors.ControlText);<br />
object currentItem = Items[e.Index];<br />
string currentText = GetItemText(currentItem);<br />
<br />
if (e.Index > -1)<br />
{<br />
SolidBrush normalBack = new SolidBrush(Color.White);
e.Graphics.FillRectangle(normalBack, rec);<br />
if (DroppedDown && !(Margin.Top == rec.Top))<br />
{<br />
int currentOffset = rec.Left;<br />
<br />
DataRow[] itemRows = valuesTbl.Select("[" + joinByField + "]='" + currentText + "'");<br />
<br />
SolidBrush HightlightedBack = new SolidBrush(System.Drawing.SystemColors.Highlight);<br />
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)<br />
{<br />
e.Graphics.FillRectangle(HightlightedBack, rec);<br />
}<br />
StreamWriter sw = new StreamWriter(File.OpenWrite("record"));<br />
foreach (DataRow currentRow in itemRows)<br />
{<br />
bool addBorder = false;<br />
<br />
foreach (object dataRowItem in currentRow.ItemArray)<br />
{<br />
string value = dataRowItem.ToString();
<br />
<br />
<br />
#region DrawLine<br />
if (addBorder)<br />
{<br />
SolidBrush gridBrush = new SolidBrush(Color.Gray);
long linesNum = lineWidth;<br />
while (linesNum > 0)<br />
{<br />
linesNum--;<br />
Point first = new Point(rec.Left + currentOffset, rec.Top);<br />
Point last = new Point(rec.Left + currentOffset, rec.Bottom);<br />
e.Graphics.DrawLine(new Pen(gridBrush), first, last);<br />
currentOffset++;<br />
}<br />
}<br />
else<br />
addBorder = true;<br />
#endregion<br />
<br />
SizeF extent = e.Graphics.MeasureString(value, e.Font);<br />
Rectangle textRec = new Rectangle(currentOffset, rec.Y, (int)extent.Width + 20, rec.Height);<br />
<br />
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)<br />
{<br />
SolidBrush HightlightedText = new SolidBrush(System.Drawing.SystemColors.HighlightText);<br />
e.Graphics.FillRectangle(HightlightedBack, currentOffset, rec.Y, fixedAlignColumnSize, extent.Height);<br />
e.Graphics.DrawString(value, e.Font, HightlightedText, textRec); sw.Write(value + "|");<br />
}<br />
else<br />
{<br />
e.Graphics.FillRectangle(normalBack, currentOffset, rec.Y, fixedAlignColumnSize, extent.Height);<br />
e.Graphics.DrawString(value, e.Font, NormalText, textRec); sw.Write(value + "|");<br />
}<br />
currentOffset += fixedAlignColumnSize;<br />
}<br />
sw.WriteLine();<br />
}<br />
sw.Close();<br />
}<br />
else<br />
e.Graphics.DrawString(currentText, e.Font, NormalText, rec);<br />
}<br />
}<br />
<br />
}
|
|
|
|
|
Hello!
First, thanks for the interest for this approach.
Second, I succeeded to reproduce that issue you reported.
Third, my exercise is build in a very simple restricted way just to show the approach. That means that I used the combobox first column text be used as unique key for the all the data inside the combobox. It is very far from having a full generic control
Now, after all the excuses are said , in order to fix this behavior (I didn't fully tested this solution so please debug it!),
please make the following change in OnDrawItem method:
1. comment the following row:
DataRow[] itemRows = valuesTbl.Select("[" + joinByField + "]='" + currentText + "'");
2. change the following row:
DataRow currentRow = itemRows[0];
to:
DataRow currentRow = valuesTbl.Rows[e.Index];
Now it will mean that we don't search values in table by key but by their order in combobox.
Please be cautive with that, I didn't test this solution deeply!
This way will cause the joinFieldName property to loose it's meaning!!!
I will try to find time in near future to make this approach being more generic.
I hope it will help you
Thanks
IssaharNoam
|
|
|
|
|
Greetings!
Thank you for your answer and the problem is solved now!
You solve the problem in an easy way. I tried to add another foreach loop to display all the rows selected, but failed at end. It seems that I'm not quite understand the principle here in OnDrawItem function.
Since I'm kinda hurry in getting the answer, I posted a thread in MSDN forum. Luckily, I got an best answer.
Here's the link to the page, this is also the formal way to solve this kind of problem, in my opinion.
Hope this can give you a new idea.
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2208758&SiteID=1[^]
Again, thanks for your help;)
|
|
|
|
|
how do you make it so the Multi Column Combo Cell always shows the drop down arrow?
|
|
|
|
|
nvm figured it out, you just change
newColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
to this:
newColumn.DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton;
|
|
|
|
|