Hi,
I'm using an ultra grid where all of the cells in a column can be assigned a different embeddable editor.
In one particular cell, I would like to set it up to use the currency editor and also associate it with a drop down list of values. Sometimes I would like to be able to type into the cell and restrict the value entered to one of the drop down list of values. Other times I would like the ability to be able to type any value into the cell, regardless of the values available in the drop down list.
I can manage to either setup the currency editor without a drop down, or setup the required drop down behaviour without the currency formatting.
My question is:- Can anyone tell me how to setup a cell, formatted for currency entry, and provide a drop down list of values for that cell?
I've tried using a drop down button with the currency editor but all to no avail. If anyone could tell me whether what I'm trying to do is possible or not, and if it is possible to provide some code, then I would be extremely grateful.
Thanks in advance,
Darren.
Hi Darren,
There's no really easy way to do this.
A dropdown list in a cell is provided by the editor for that cell. And the UltraCurrencyEditor doesn't have any support for a ValueList or an automatic dropdown.
It is possible to do this, but it takes a little bit of coding. Here's what you do:
This gives you a CurrencyEditor in a grid cell with a dropdown list - after you populate the list control, of course.
Now, to make this work like a dropdown list, you have to do two more things:
Hi Mike,
Thank you for your extremely prompt and detailed reply.
I've just got round to trying your solution, and everything works well (using an UltraNumericEditor using an UltraDropDownButton with an UltraGrid control) apart from one issue that I have i.e. there doesn't appear to be an AfterEditorButtonDropDown event with the UltraNumericEditor that I'm using!
But there is a BeforeEditorButtonDropDown that I'm trying to use instead. However, using this event, the first time that the grid drops down, there doesn't appear to be any data in the grid (at that time) for me to loop on in order to explicitly specify the currently "selected" row. This behaviour only occurs the very first time before the grid drops down. On subsequent attempts, I can loop on the data, and find the appropriate row to mark as selected.
I'm using the SetDataBinding method when I construct the grid, and I even tried calling DataBind explicitly from the BeforeEditorButtonDropDown event, both to no evail. In fact calling DataBind explicitly makes matters even worse as then I never appear to have any rows to loop on!
I've pasted a copy of the code that I'm using in my BeforeEditorButtonDropDown event below. The "UltradropDownHelper" that I'm using is just a class derived from the UltraGrid.
void numericEditor_BeforeEditorButtonDropDown(object sender, BeforeEditorButtonDropDownEventArgs e) { UltraGridCell gridCell = (UltraGridCell)(e.Context); decimal value = Convert.ToDecimal(gridCell.Value); UltraDropDownHelper ultraDropDownHelper = (( UltraDropDownHelper)(((DropDownEditorButton)(e.Button)).Control)); //ultraDropDownHelper.DataBind(); UltraGridBand gridBand = ultraDropDownHelper.DisplayLayout.Bands[0]; foreach (UltraGridRow row in gridBand.GetRowEnumerator(GridRowType.DataRow)) { if (Convert.ToDecimal(row.Cells["Value"].Value) == value) { row.Selected = true; break; } } } I would appreciate it very much if you could have a look at the code for me, and perhaps give me a few pointers as to what I'm doing wrong. I would appreciate it very much if you could have a look at the code for me, and perhaps give me a few pointers as to what I'm doing wrong.
void numericEditor_BeforeEditorButtonDropDown(object sender, BeforeEditorButtonDropDownEventArgs e) {
{
UltraGridCell gridCell = (UltraGridCell)(e.Context);
decimal value = Convert.ToDecimal(gridCell.Value);
UltraDropDownHelper ultraDropDownHelper = ((
((
UltraDropDownHelper)(((DropDownEditorButton)(e.Button)).Control));
//ultraDropDownHelper.DataBind();
UltraGridBand gridBand = ultraDropDownHelper.DisplayLayout.Bands[0];
foreach (UltraGridRow row in gridBand.GetRowEnumerator(GridRowType.DataRow)) {
if (Convert.ToDecimal(row.Cells["Value"].Value) == value) { row.Selected =
row.Selected =
true;
break; } } } I would appreciate it very much if you could have a look at the code for me, and perhaps give me a few pointers as to what I'm doing wrong.
}
I would appreciate it very much if you could have a look at the code for me, and perhaps give me a few pointers as to what I'm doing wrong.
Yours sincerely,
Hi again,
I also have an additional problem when I attempt to determine which row the user selected from the drop down grid i.e. if the user clicks on the column header (which should just either re-sort or filter), the row is being reported as a "data row", in fact the first data row in the grid.
The code that I'm using in my mouse down event is as follows:
void UltraDropDownHelper_MouseDown(object sender, MouseEventArgs e) {
UIElement aUIElement = DisplayLayout.UIElement.ElementFromPoint(e.Location);
UltraGridRow row = (UltraGridRow)aUIElement.GetContext(typeof(UltraGridRow));
if ((row != null) && (row.IsDataRow == true))
// Process the selected row here as appropriate
Regardless of whether I'm using e.Location or e.X and e.Y as the "Point", the result is the same. When I click on the very top left of the grid (i.e. point 0,0), the row always seems to come back as the very first data row!!!
Okay, I'm pretty sure these issues are easy to solve. :)
1) The grid probably has no data the first time because it either hasn't been painted, yet (since it has never been made visible) or because it's not contained in anything.
For the former, the solution is to simply call the Refresh method on the grid after you bind it.
If it's the latter, then you need to set the BindingContext on the grid to the BindingContext of the Form. I'm not absolutely sure if it's better to do this before or after teh grid is bound, but either one will probably work.
2) The reason this happens is that the header elements are associated with the first row in the grid, so GetContext will return the row. The thing to do is to call GetAncestor on the UIElement and make sure you get a RowUIElement before you call GetContext.
But in this case, you really don't need to use UIElements at all. You should just use the grid.ActiveRow. This is better, anyway, since you can use the same thing if the user arrows through the rows in the grid and presses Enter, for example.
Brilliant, thank you very, very much.
I've now managed to get the functionality I require by implementing your solutions as follows:
1) I had to set the BindingContext on the drop down grid.
2) I used the GetAncestor method to check that the row actually is a RowUIElement. I may be wrong, but I don't think that I could use the ActiveRow as this could initially be set if the main grid cell already contains a value. In this situation, I'm assuming that by clicking on a header, ActiveRow is still going to be set to this initial row, which is what I don't want to return. I just want a click on the header to behave as usual i.e. either sort or filter.
I understand your explanation as to why the header is regarded as a row, but I'm still a bit confused as to why the IsDataRow property returns true. Anyway, thanks to you, I now have a solution and am extremely grateful for all your help.
As an aside, I'm now having a spot of trouble with an UltraDropDown i.e. if the user clicks on any other part of the application outside of the drop down, I want whatever UltraDropDown is active on a grid to close. I'm aware that I can use the dropDownManager in order to close any drop down, but I don't want to pepper my code with calls to that close method.
My question is:- is there any event that I can trap in order to close the UltraDropDown? I've tried the LostFocus event of the UltraDropDown but apparently the controls CanFocus property always comes back with false, and therefore this event will never get generated.
I would appreciate any suggestions that you might have relating to this issue.
Thankyou once again.