Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS Tech Support » Controlling Sort Order in CExtReportGridWnd Collapse All
Subject Author Date
Henri Hein Aug 30, 2007 - 8:32 PM

When the user sorts on a column in a CExtReportGridWnd, we want to use some underlying data to sort on, not the actual data in the column.

I tried setting up a CExtReportGridSortOrder, but it’s unclear how and when to use this. I tried overriding ReportSortOrderGet(), but this appears to be ignored. (BTW, it’s also called quite a surprising number of times during initial population of the grid, but that is probably not related). Calling ReportSortOrderSet() likewise appears ignored.

It’s possible I don’t understand how to use the ReportGridSortOrder class. Do I add new columns to it, or columns from the grid, or columns from the underlying data provider? It’s all pretty confusing.

Any pointers would be appreciated.

Henri Hein Sep 6, 2007 - 1:14 PM

I can’t get this to work. The CTOR on my specialization is getting called when I call ReportItemGetCell(), so it seems like the grid is using my class. However, Compare() or Assign() on my class never gets called.

I got most of my problems solved with the OnGbwAnalyzeCellMouseClickEvent() override. I figure out which column was clicked, then tell the grid to sort on the surrugate column instead, using a ReportGridSortOrder instance over that column.

I still have two problems:
1. There is no visual indication which column is sorted on -- or rather, which column the user thinks was sorted on. I’d like to somehow indicate the column the user clicked, so they have an idea what the current sort data is.
2. Texts are not sorted alphabetically. You have advised in the past to use a cell class override to overcome this problem, but since I can’t get that to work, I either need help with that or an alternate suggestion.

Technical Support Sep 7, 2007 - 5:21 AM

If some overridden virtual methods are not called, you should try these steps:

1) Check the signatures of the overridden methods again in order to make sure there are no typos. They should be exactly the same as in the base class.

2) Rebuild your project completely using the Build | Rebuild menu command in Visual Studio.

3) Send us the source code of your cell class so we can check it ourselves.

The sorted columns are visible as sorted because their header captions contain sort arrows. It seems you want to higdhlight grid cell backgrounds for all the cells in all the sorted columns. In this case you should override the following virtual method in your grid class:

virtual bool OnGridHookCellPaintBackground(
            const CExtGridCell & _cell,
            CDC & dc,
            LONG nVisibleColNo,
            LONG nVisibleRowNo,
            LONG nColNo,
            LONG nRowNo,
            INT nColType,
            INT nRowType,
            const RECT & rcCellExtra,
            const RECT & rcCell,
            const RECT & rcVisibleRange,
            DWORD dwAreaFlags,
            DWORD dwHelperPaintFlags
            ) const;
In the case of report grid, you can invoke pGrid->GridCellGetOuterAtTop( nColNo, 0L ) to get a pointer to a CExtReportGridColumn object which indentifies the report column and then check if it presents in the current sort order. Your virtual method should simply return false for unsorted columns. It should fill the custom background in the rcCellExtra rectangle and return true for sorted columns. The CExtReportGridWnd::ReportSortOrderGet() method returns a reference to the CExtReportGridSortOrder object which describes the current sorting rules. The CExtReportGridSortOrder::ColumnGetIndexOf() method allows you to determine if the CExtReportGridColumn object is present in the sort order.

Henri Hein Aug 31, 2007 - 7:19 PM

Update:

From your example I realized I could just cast a newly added cell to my own type. However, this just helped me confirm that my data is added to the specialized cell correctly. The ’Compare()’ method never gets called.

Technical Support Sep 1, 2007 - 7:16 AM

Your grid cell class should look like:

class CYourGridCell : public CExtGridCellString
{
public:
      DECLARE_SERIAL( CYourGridCell );
      IMPLEMENT_ExtGridCell_Clone( CYourGridCell, CExtGridCellString );
      CYourGridCell( CExtGridDataProvider * pDataProvider = NULL )
            : CExtGridCellString( pDataProvider )
      {
      }
      CYourGridCell( const CExtGridCell & other )
            : CExtGridCellString( other )
      {
      }
      virtual int Compare(
            const CExtGridCell & other,
            DWORD dwStyleMask = __EGCS_COMPARE_MASK,
            DWORD dwStyleExMask = __EGCS_EX_COMPARE_MASK
            ) const
      {
            ASSERT_VALID( this );
            CYourGridCell * pCell =
                  DYNAMIC_DOWNCAST(
                        CYourGridCell,
                        ( const_cast < CExtGridCell * > ( &other ) )
                        );
            if( pCell == NULL )
                  return
                        CExtGridCellString::Compare(
                              other,
                              dwStyleMask,
                              dwStyleExMask
                              );
            // The other cell is also CYourGridCell, compare properties
            // of CYourGridCell here and return -1 or +1 if they are not equal.
            return CExtGridCellString::Compare( other, dwStyleMask, dwStyleExMask );
      }
      virtual void Assign( const CExtGridCell & other )
      {
            ASSERT_VALID( this );
            CExtGridCellString::Assign( other );
            CYourGridCell * pCell =
                  DYNAMIC_DOWNCAST(
                        CYourGridCell,
                        ( const_cast < CExtGridCell * > ( &other ) )
                        );
            if( pCell != NULL )
            {
                  // The other cell is also CYourGridCell, assign properties
                  // of CYourGridCell class here.
            }
            else
            {
                  // The other cell is not CYourGridCell, clear properties
                  // of CYourGridCell class here.
            }
      }
};

// This line of code should be in beginning of .CPP file before
// definition of MFC’s debug new operator:
IMPLEMENT_SERIAL( CYourGridCell, CExtGridCellString, VERSIONABLE_SCHEMA|1 );
That is the minimal implementation of a custom grid cell class which is compared during sorting and can be cloned for storing inside the grid’s data provider which manages a special memory pool for cell objects. If you need to copy/paste/save restore grid cells of your type, the you should also implement the Serialize() virtual method. We have used the CExtGridCellString class as the base in the sample code above. It can be of any different grid cell class in your project.

Henri Hein Sep 1, 2007 - 1:37 PM

OK, I didn’t know the Assign() method was required. I will try that.

Thanks,
- Henri

Henri Hein Aug 31, 2007 - 6:57 PM

This doesn’t work. I tried creating my own cell class and overrode the Compare() method. I had two big problems with this approach to begin with. First, I’m not looking to change behavior at the cell level, but at the column level, so creating a specialized cell class did not make a lot of sense. Secondly, you do not provide a way to get instances of my own class back from the grid, at least not that I could find, so I had to rely on the embedded LParam value to store my sort value. Even with this workaround, my specialization was ignored and the grid still got sorted as it used to.

The solution still seems to be in the ReportSortOrderGet() override. I was able to get this override to work, at least on initial sorting, but I haven’t found a way to intercept the sort events and impose my sort order at that time.

Technical Support Aug 31, 2007 - 12:56 PM

Assigning the sort/group order to the report grid control activates an algorithm which rebuilds and resorts tree items in the report grid control. All the rows are compared with each other. All the grid cells are also compared with each other for all the sorted columns. The comparison of two grid cells in each column is performed in the CExtGridCell::Compare() method. So if you want to implement a custom sorting, you should simply create and use a custom grid cell class, which is derived from some Prof-UIS grid cell class, that implements the virtual method mentioned above.