In CListCtrl, is there any way to have a value of one column dependent on another?
For example- My grid has four column, I want column #4 to always have value equal to column#2 - x( x is some variable)
Is there any direct way to this in MFC.
I want column#4 to update data automatically whenever data in column#2 changes.
Thanks.
Related
The context
In a wxWidgets (version 3.0.2) C++ application, I am trying to hide the first column of a wxListCtrl.
I did not find a member function to do this so I tried to set the width of the column to 0:
myListCtrl->SetColumnWidth(0, 0);
first argument being the column ID and second one the width in pixels (wxListCtrl documentation).
After running the program, the header of the first column is hidden as I wanted but the data of each row of the first column overlaps the data of each row of the second column (which is not hidden). It is obviously not what I want. The header and the data of the first column should be hidden.
The question
In wxWidgets 3.0.2, is there a way to hide the first column (header and data of each rows) of a wxListCtrl?
I don't believe you can. You have a few options.
Delete the column using DeleteColumn(int columnIndex). You aren't losing any data, just the display of it, so you can always re-insert the column and repopulate it if you need to re-add it. Obviously this could be time consuming if your data is excessively large.
Depending on your application, just don't create the column in the first place. You don't say why you want to hide it, so if you just don't want it, don't add it.
Implement your control as a virtual control which gives your application control over what to display where. The burden of data display management falls to you to do manually but you have a great deal more flexibility. Inherit the class with wxLC_VIRTUAL style and implement OnGetItemText http://docs.wxwidgets.org/3.0/classwx_list_ctrl.html#a92370967f97215e6068326645ee76624
Edit:
To expand on the comment question, how to get the selected item index:
The wxListCtrl is a little weird when it comes to selected items. I'm sure it has to do with needing to support report, icon, etc. different views. When dealing with a multi-column report mode, you might find that you can only select items in the first column. If you are on Windows, it should automatically be set to "Full Row Select" but I don't know about other OSs.
Anyway, here is a utility method that returns the first selected item (note that you can support multi-selection if you want to).
//Get the item currently selected
int ListView::GetItemSelected() const
{
for(int i=0; i<GetItemCount(); ++i)
if (GetItemState(i, wxLIST_STATE_SELECTED) == wxLIST_STATE_SELECTED)
return i;
return -1;
}
If you want (and it makes sense), you can connect the list item selected event.
this->Connect(wxEVT_COMMAND_LIST_ITEM_SELECTED, wxCommandEventHandler(ListView::selected_Changed), NULL, this);
and within that event handler, get the selected item and do what needs doing (depending entirely on your application).
You will note that I'm using a derived class here which just makes things a lot easier but you don't have to. You can connect to something like MyMainForm::sqlResults_selectedChanged or whatever.
There is more than one way to accomplish all this and you can also find some good suggestions and help here: https://wiki.wxwidgets.org/WxListCtrl
I have a situation where I'm using the IEditorDataFilter interface within a custom UltraGrid editor control to automatically map values from a bound data source when they're displayed in the grid cells. In this case it's converting guid-based key values into user-friendly values, and it works well by displaying what I need in the cell, but retaining the GUID values as the 'value' behind the scenes.
My issue is what happens when I enable the built-in group by functionality and the user groups by a column using my editor. In that case the group by headers default to using the cell's value, which is the guid in my case, so I end up with headers like this:
Column A: 7F720CE8-123A-4A5D-95A7-6DC6EFFE5009 (10 items)
What I really want is the cell's display value to be used instead so it's something like this:
Column A: Item 1 (10 items)
What I've tried so far
Infragistics provides a couple mechanisms for modifying what's shown in group by rows:
GroupByRowDescriptionMask property of the grid (http://bit.ly/1g72t1b)
Manually set the row description via the InitializeGroupByRow event (http://bit.ly/1ix1CbK)
Option 1 doesn't appear to give me what I need because the cell's display value is not exposed in the set of tokens they provide. Option 2 looks promising but it's not clear to me how to get at the cell's display value. The event argument only appears to contain the cell's backing value, which in my case is the GUID.
Is there a proper approach for using the group by functionality when you're also using an IEditorDataFilter implementation to convert values?
This may be frowned upon, but I asked my question on the Infragistic forums as well, and a complete answer is available there (along with an example solution demonstrating the problem):
http://www.infragistics.com/community/forums/p/88541/439210.aspx
In short, I was applying my custom editors at the cell level, which made them unavailable when the rows were grouped together. A better approach would be to apply the editor at the column level, which would make the editor available at the time of grouping, and would provide the expected behavior.
This question is to understand how to update any row programatically.
Details.
I have a listcrtl, that accepts the data from either from a file or from the edit controls in the dialog. When the items are added I will know its position, that I added, so I can change its subitem texts. I have even implemented the sort functionality in the list, so now the position keeps changing. I have an identifier column for each row, so that I can recognize the row.
Now, from an out side event, if I have to change an other columns value of an ID that I know , I have to first find the position of the item by comparing the id column, then with that position, I have set the subitemtext.
This works fine except that it takes time to find the row first then it need to update the column.
Now, in order to get the row directly, I need some help.
I have gone through
http://msdn.microsoft.com/en-us/library/windows/desktop/hh298346(v=vs.85).aspx
But this does not use MFC. Please help me achieving this.
If you have many items you should consider switching to Virtual Lists. It is the fastest way to access the data. If you do not want to invest time to this, then the easiest way for you will be the following:
When you populate the CListCtrl store the ID of each item in the item data using the SetItemData() method. The ID will always be associated with the item, even after re-sorting.
When you need to locate the required item, just scan all items, but do not use GetItemText(). Use GetItemData() instead. This will be faster
I'm working on an implementation of tables in a Qt app, but having a bit of trouble getting the design right.
I have two classes, Table and Cell.
Cell has API for setting cell properties such as borders and paddings, and getting the row and column of the cell using int Cell::row() and int Cell::column(). It is an explicitly shared class, using QExplicitlySharedDataPointer for its data. It also has an isValid() API to query if the cell is valid or not.
Table has API for inserting/removing rows and columns and merging areas of cells. A Cell may be retrieved from a table using Table::cellAt(int row, int column). Rows of cells are kept as a QList<QList<Cell>>. When rows and columns are removed, the removed cells are marked as invalid by the table, which makes calls to Cell::isValid on any previously returned cells from the removed rows/columns return false.
Now to the tricky part: Since calculating the row and column number of a cell if you haven't already got them is an expensive operation, the Table::cellAt(int row, int column) methods sets the row/column explicitly on the Cell before returning it and the Cell keeps them as simple int members. This means a Cell can reply fast when queried for its row/column.
But here comes the problem; This also means that the values of Cell::row() and Cell::column will be incorrect if rows or columns are removed/inserted before the row/column that the cell is in.
I can't mark the affected cells as invalid in the same way I do when the actual row/column they are part of is removed. Since later on someone might again retrieve a cell with cellAt(int, int) in that row/column. And that cell should not be invalid.
Does anyone have some advise on a better design here?
You could do a lazy update. That is, instead of updating the cell's position information every time the table changes, only update it when Cell:row or Cell:column are called if the table has changed since the last time the cell's position was updated. That would require you to keep a version stamp or something in Table and Cell. Every time the table gets updated, bump the version. Cell::row and Cell:column would first check if the Cell's version is older than the Table's, and if so, recalculate the position.
Whether that extra work is worth it versus just always recalculating position or recalculating on every change, I can't say.
I discussed this problem with a friend because it seemed too much like a Programming Pearls exercise. This is what we came up with:
Create a new structure for counting indices. It could be something like struct Index { int n; };.
Store row and column indices in two QList<Index*>. Let's call these Dimension. Using a pointer is crucial, as you'll see later.
Cells do not store their row and column values anymore. They point to an element at each of the two Dimension. When queried for their row and column, there is now an extra pointer dereference which should not be too expensive.
When the table has rows and columns added or removed, you add items to or remove items from the corresponding Dimension and update the n value of the following items. Storing pointers is necessary because QList copies its values.
Instead of renumbering every Cell affected by a table manipulation, an operation that has a cost of O(rows x columns), you'll now update only the affected rows or columns, which has cost of O(rows + columns). The downside is added code complexity and two dereferenced accesses when the Cell is queried for its row or column.
I am creating images dynamically in BIRT and adding them to a cell of a grid. The grid is part of a List, which iterates over the records in the data source.
I want to be able to modify the properties of the images on a per-record basis. Specifically I am changing the margins - but my problem is that I cannot find the way to access the contents of the cell.
I expected that I could use the 'this' keyword in the cell's onRender function and it would provide me a handle to access the cell's contents.
This function does not seem to work though - it is apparently a different object type.
How do I access the children of an individual instance of a cell?