I have a calculated numeric field in a grid. I use a custom editor for it. All filter operations in Filter editor work well but the auto filter row filters according to the value and not the display text. I know that I can set FilterMode to DisplayText but then this is also used for comparisons etc. So, I need to use FilterMode DisplayText for the auto filter, Value for everything else. Is this possible? I have already a lot of code in the custom grid class, so it would be ok to have an additional event handler or another workaround.
EDIT
I store e.g. prices in euro and I display them differently depending on the user's settings. So, e.g. I have stored a value 100 and I need to display "234 abc". When I set FilterMode=DisplayText, I can't compare the actual value with e.g. > and <. Currently, I use FilterMode=Value and I convert the displayed value in the filter editor for filtering. The only problem is with StartsWith i.e. auto filter and with = because of rounding. How could I fix that?
I found a solution for my issue... As I have no control on how exactly the values are filtered and I had couple of problems with filtering, I converted my bound columns to unbound columns. I removed the editors making the conversions and replaced them by unbound expressions with custom functions + display format. Not really the solution I was searching for but it works for all kinds of filtering.
Related
In a wxpython Combobox, long strings get left-truncated in the dropdown portion. This can result in some values looking identical when they aren't. I'd like to provide better information to the user than that.
The following options occur to me:
Insert elipses in the middle of the string before adding it to the combobox's dropdown choices and expanding it back before placing back in the edit portion.
Show a tooltip of the full string when the user mouses/hovers over a value in the dropdown.
Problem is, the Combobox class does not expose events that enable either of the above.
How can I intercept the events corresponding to either of the above? Any other ideas for making long combobox strings visible to the user?
Thanks,
RichK
I would recommend using the ComboCtrl instead of the ComboBox. The benefit is that the ComboCtrl is a custom widget, so it allows more flexibility. For example, the ComboCtrl provides a scrollbar for long strings. Check out the wxPython demo for some good examples.
I have read all sorts of documents across the web about what should be a farly common and painless implementation. Since I have found no consistent and slick reply (even the Embarcadero website describes some properties wrong!) I am going to post a "short" howto.
Typical, frequent use case: the developer just wants to painlessy show a couple of database-extracted information in a combo box (i.e. a language selection), get the user's choice out of it and that's it.
Requirements:
Delphi, more or less any version. VCL is covered.
A database table. Let's assume a simple table with an id and value fields.
A DataSet (including queries and ClientDataSets).
A DataSource linked to the DataSet.
A TDBLookupComboBox linked to the DataSource that shall show a list of values and "return" the currently selected id.
Firstly, we decide whether the sort order is the one we want or not and if all the items in that table must be shown. Most often, a simple ORDER BY clause or a DataSet index will be enough. In case it's not, we may add a sort_order field and fill it with integers representing our custom sort order. In case we want to show just some items, we add a visible or enabled field and use it in our SQL. Example:
SELECT id, value
FROM my_database_table
WHERE visible = 1
ORDER BY sort_order
I have defined visible as INTEGER and checking it against 1 and not TRUE because many databases (including the most used SQLite) have little support for booleans.
Then an optional but surprisingly often nice idea: temporarily add a TDBGrid on the form, link it to the same TDataSource of the TLookupComboBox and check that you actually see the wanted data populate it. In fact it's easy to typo something in a query (assuming you are using a SQL DataSet) and get no data and then you are left wondering why the TDBLookupComboBox won't fill in.
Once seen the data correctly show up, remove the grid.
Another sensible idea is to use ClientDataSets for these kinds of implementations: due to how they work, they will "cache" the few rows contained in your look ups at program startup and then no further database access (and slowdown and traffic) will be required.
Now open the TDBLookupComboBox properties and fill in only the following ones:
ListSource (and not DataSource): set it to the TDataSource connected to the DataSet you want to show values of.
ListField: set it to the field name that you want the user to see. In our demo's case it'd be the value field.
KeyField: set it to the field name whose value you want the program to return you. In our demo it'd be the id field.
Don't forget to check the TabOrder property, there are still people who love navigating through the controls by pressing the TAB key and nothing is more annoying than seeing the selection hopping around randomly as your ComboBox was placed last on the form despite graphically showing second!
If all you need is to show a form and read the TDBLookupComboBox selected value when the user presses a button, you are pretty much sorted.
All you'll have to do in the button's OnClick event handler will be to read the combo box value with this code:
SelectedId := MyCombo.KeyValue;
Where SelectedId is any variable where to store the returned value and MyCombo of course is the name of your TDBLookupComboBox. Notice how KeyValue will not contain the text the user sees onscreen but the value of the id field we specified in KeyField. So, if our user selected database row was:
id= 5
value= 'MyText'
MyCombo.KeyValue shall contain 5.
But what if you need to dynamically update stuff on the form, depending un the combo box user selection? There's no OnChange event available for our TDBLookupComboBox! Therefore, if you need to dynamically update stuff around basing on the combo box choices, you apparently cannot. You may try the various "OnExit" etc. events but all of them have serious drawbacks or side effects.
One possible solution is to create a new component inheriting from TDBLookupComboBox whose only task is to make public the hidden OnChange event. But that's overkill, isn't it?
There's another way: go to the DataSet your TDBLookupComboBox is tied to (through a DataSource). Open its events and double click on its OnAfterScroll event.
In there you may simulate an OnChange event pretty well.
For the sake of demonstration, add one integer variable and a TEdit box to the form and call them: SelectedId and EditValue.
procedure TMyForm.MyDataSetAfterScroll(DataSet: TDataSet);
var
SelectedId : integer;
begin
SelectedId := MyDataSet.FieldByName('id').AsInteger;
EditValue.Text := MyDataSet.FieldByName('value').AsString;
end;
That's it: you may replace those two demo lines with your own procedure calls and whatever else you might need to dynamically update your form basing on the user's choices in your combo box.
A little warning: using the DataSet OnAfterScroll has one drawback as well: the event is called more often than you'd think. In example, it may be called when the dataset is opened but also be called more than once during records navigation. Therefore your code must deal with being called more frequently than needed.
At this point you might rub your hands and think your job is done!
Not at all! Just create a short demo application implementing all the above and you'll notice it lacks of an important finishing touch: when it starts, the combo box has an annoying "blank" default choice. That is, even if your database holds say 4 choices, the form with show an empty combo box selected value at first.
How to make one of your choices automatically appear "pre-selected" in the combo box as you and your users expect to?
Simple!
Just assign a value to the KeyValue property we already described above.
That is, on the OnFormCreate or other suitable event, just hard-code a choice like in example:
MyCombo.KeyValue := DefaultId;
For example, by using the sample database row posted above, you'd write:
MyCombo.KeyValue := 5;
and the combo box will display: "MyText" as pre-selected option when the user opens its form.
Of course you may prefer more elegant and involved ways to set a default key than hard-coding its default value. In example you might want to show the first alphabetically ordered textual description contained in your database table or whatever other criterium. But the basic mechanic is the one shown above: obtain the key / id value in any manner you want and then assign it to the KeyValue property.
Thank your for reading this HowTo till the end!
I am developing several dozen reports in SSRS 2008 R2. I am finding the formatting of cells to be the most tedious and error prone part of the task. I know how to individually format each cell.
Is there a way to copy the format of one cell to many other cells?
I would like to avoid doing search and replace in XML, but I am open to it. My dataset queries are parameterized MDX.
Is it possible to format an entire column at once? Or do you always have to format each individual textbox in a column? Is there a way to specify default formatting for each textbox?
Working on the assumption that you're right-clicking each Text Box and using TextBox Properties to edit the formatting options:
If you go to the View menu in BIDS and select Properties Window, you will get access to all properties of each object at once (in my BIDS it displays below the Solution Explorer on the right).
Assuming you're talking about a Tablix control within a report here, You can format an entire column simply by clicking the column header and editing the formatting options in the Properties Window.
When it comes to say 4 or 5 cells together but not an entire column/row, you can shift-click to allow you to format multiple cells in one go.
I.e. click Cell 1, hold down shift and then click Cell 4. The Properties Window will then let you edit all the cells in the selected range.
Riffing off of GShenanigan's answer, it depends on what you mean by formatting. If it's things like color, font, etc, then you could define a variable, set it to the value that you want, and then set the value of the property for the cell(s) to the value of that variable. For instance, let's say that you're going to set all of the cells' font to Courier New. You'd define a variable called "Font", set it to "Courier New", and then for each cell that you want to have this font, you'd set it's value using an expression which evaluates that that variable's value. Then, when the requirements change and all of those cells need to be Arial now, you change it in one place (the variable) and all the formatting changes.
My solution was to highlight all cells in the table that I wanted to change. Then click View to display the Properties box. Go under the Properties box, in the Number section and change the Format. This worked and reformatted all cells as I wanted.
As a note, I had to paste in the format that I wanted from one of the cells that I had already changed.
Steps:
1. Format one textbox with your desired format
2. Select that cell and check its property window and in "Format" area you will see some code
3. copy that and select other textboxes you want to format with same format.
4. paste the copied value in format area of these newly selected textboxes.
5. Finished.
Highlight cells you want to change and set the font using the Report Formatting toolbar. This worked for me after not being allowed to type in the Properties side pane and having the Properties option disabled on the context menu.
You can format a column or a row depending on what conditions you will require for the formatting.
Let's look at the different scenarios (assuming you are using Visual Studio /BIDS:
If all your columns or rows use similar conditions for formatting
you can select the entire row or column => go to properties window => write an expression for the formatting
If a portion of your columns require use similar conditions for formatting, you can pick those columns by using the control key and clicking on these columns and apply the formatting as explained above
If each cell's formatting is based on individual conditions (e.g., you evaluate the data from that cell to format that cell), you either format particular cells or write an external script code
I have a Silverlight Toolkit datagrid where one column shows textual representation of a numeric value. I would like to sort on the column's underlying numeric value but present the text data to the user. Values in the grid column are in a format such as:
A Category (200-300)
Some Category (100-200)
Yet Another Category (300-400)
As these values are textual the grid is correctly sorting on the text, however I have a custom Comparer which can already sort these by the numeric categories and would like to plug it into the grid.
The data-object that the grid cell is binding to only has the textual representation (and no way of easily adding the numeric value). Therefore, SortMemberPath= won't work in this case.
Is it possible to inject a custom comparer for a single grid column and sort on that? Or perhaps implement a CollectionViewSource with custom comparer? Remember this is Silverlight, not WPF so some fields/properties/classes are missing when compared to WPF.
The simplest way I feel to achieve this is to add two properties to entity that you are binding to grid one will be the text and the other can be numeric and binding only one to column of grid and other you can use in SortMemberPath. If not two properties you want to keep in entity then, you can keep Numeric only and use converter to convert it into text and SortMemberPath=NumericPropertyName.
In ExtJS, say you have a simple editorgrid with two columns, X and Y, both of which have a combo box as their editor.
How is is possible to make the values available in the second column's combo box (Y) depend on the selected value in the first column (X)?
So, depending on what is selected in X, the values available in Y change accordingly.
Assuming that you have a store backing each combobox, you can use the store's filter or filterBy methods to narrow down the results of one combobox based on the other's current selection. You can call either filter function on the 'select' or 'change' events of the combobox. I've used this method successfully in the past, and it worked well for my needs. I had around 200 records per combobox, so I'm not sure how well this solution scales if you have a good deal records more than that.
Managed to answer my question:
As the EditorGrid in question uses a RowSelectionModel (not a CellSelectionModel), I was able to add the below to the beforeselect event of the editor combobox:
Ext.getCmp('EDITORGRID').selModel.getSelected().set('colY','myvalue');
Having updated the relevant store as necessary, myvalue was simply set to the first record returned.
Here is a working example from JoeKuan