OK, another signature bug with a fix. I fixed this one OUTSIDE of the Codejock library, but the fix should really be migrated to the library itself.
The problem was that calling RemoveRecordEx was leaving the selection at exactly the same indexes as before, which following a removal usually meant the wrong row. In my case, this was reall wierd, since clicking on a row would occasionally remove other rows in the report, causing the selected row to be a row other than the one that was clicked on.
The solution is fairly basic, and I have Outlined it below. In my case, I already had a derived class, so I just overloaded RemoveRecordEx, since it is virtual. The code below describes the fix.
One issue here is that fixing this in the library will break it for anybody that fixed it themselves outside the library, but I think the fix still belongs in CXTPReportControl, and not in subclasses for every program that uses it.
The fix:
// this function operates on the assumption that all rows removed will be
// in a block, all together. If more than one row is removed, the positions
// of the rows will be a to a+n, where a in the index of the first row, and
// n is the number of rows removed. Provided this is true, we can adjust the
// selection as a block, even when multiple rows are removed by the same call
// to this function.
// remember the index of the main row we are removing
int nIndexOfRemoval = pRecord->GetIndex();
// remember how many rows we HAD
int nOldRowCount = m_pRecords->GetCount();
// do the removal, and remember the return
BOOL bRet = CXTPReportControl::RemoveRecordEx(pRecord, bAdjustLayout);
// calculate how many rows were removed
int nRemovedRowCount = nOldRowCount - m_pRecords->GetCount();
// fix the selection positions
CXTPReportSelectedRows* pSel = GetSelectedRows();
for (int a = 0; a < pSel->m_arrSelectedBlocks.GetSize(); a++)
{
// reduce the start and end values for the block if needed
if (pSel->m_arrSelectedBlocks[a].nIndexBegin >= nIndexOfRemoval)
{
// shift it down
pSel->m_arrSelectedBlocks.ElementAt(a).nIndexBegin -= nRemovedRowCount;
// sometimes a reduction by the full count is wrong, fix this by
// capping the removal count on the bottom.
if (pSel->m_arrSelectedBlocks[a].nIndexBegin < nIndexOfRemoval)
{
pSel->m_arrSelectedBlocks.ElementAt(a).nIndexBegin = nIndexOfRemoval;
}
}
if (pSel->m_arrSelectedBlocks[a].nIndexEnd > nIndexOfRemoval)
{
// shift it down
pSel->m_arrSelectedBlocks.ElementAt(a).nIndexEnd -= nRemovedRowCount;
}
if (pSel->m_arrSelectedBlocks[a].nIndexEnd <= pSel->m_arrSelectedBlocks[a].nIndexBegin)
{
// this block has been removed out of existence
pSel->m_arrSelectedBlocks.RemoveAt(a);
a--;
}
}
// also adjust the focused row index the same way
if (m_nFocusedRow >= nIndexOfRemoval)
{
// shift it down
m_nFocusedRow -= nRemovedRowCount;
// cap it
if (m_nFocusedRow < nIndexOfRemoval)
{
m_nFocusedRow = nIndexOfRemoval;
}
}
// return
return bRet; |
|