5
5
* Date: 9/10/2006 11:15 AM
6
6
*
7
7
* Change log
8
+ * 2018-09-01 JPP - Hardened code against the rare case of the control having no columns (SF bug #174)
9
+ * The underlying ListView does not like having rows when there are no columns and throws exceptions.j
8
10
* 2018-05-05 JPP - Added OLVColumn.EditorCreator to allow fine control over what control is used to edit
9
11
* a particular cell.
10
12
* - Added IOlvEditor to allow custom editor to easily integrate with our editing scheme
@@ -4812,6 +4814,10 @@ protected OlvListViewHitTestInfo LowLevelHitTest(int x, int y) {
4812
4814
if (!this.ClientRectangle.Contains(x, y))
4813
4815
return new OlvListViewHitTestInfo(null, null, 0, null, 0);
4814
4816
4817
+ // If there are no columns, also don't bother with anything else
4818
+ if (this.Columns.Count == 0)
4819
+ return new OlvListViewHitTestInfo(null, null, 0, null, 0);
4820
+
4815
4821
// Is the point over the header?
4816
4822
OlvListViewHitTestInfo.HeaderHitTestInfo headerHitTestInfo = this.HeaderControl.HitTest(x, y);
4817
4823
if (headerHitTestInfo != null)
@@ -6157,6 +6163,8 @@ protected virtual bool HandleFindItem(ref Message m) {
6157
6163
/// search the every row until a match is found, wrapping at the end if needed.</remarks>
6158
6164
public virtual int FindMatchingRow(string text, int start, SearchDirectionHint direction) {
6159
6165
// We also can't do anything if we don't have data
6166
+ if (this.Columns.Count == 0)
6167
+ return -1;
6160
6168
int rowCount = this.GetItemCount();
6161
6169
if (rowCount == 0)
6162
6170
return -1;
@@ -6327,6 +6335,10 @@ public void ToggleSelectedRowCheckBoxes() {
6327
6335
/// <param name="m">The m to be processed</param>
6328
6336
/// <returns>bool to indicate if the msg has been handled</returns>
6329
6337
protected virtual bool HandleLButtonDown(ref Message m) {
6338
+ // If there are no columns, the base ListView class can throw OutOfRange exceptions.
6339
+ if (this.Columns.Count == 0)
6340
+ return true;
6341
+
6330
6342
// We have to intercept this low level message rather than the more natural
6331
6343
// overridding of OnMouseDown, since ListCtrl's internal mouse down behavior
6332
6344
// is to select (or deselect) rows when the mouse is released. We don't
@@ -6395,6 +6407,10 @@ protected virtual bool ProcessLButtonDown(OlvListViewHitTestInfo hti) {
6395
6407
/// <param name="m">The m to be processed</param>
6396
6408
/// <returns>bool to indicate if the msg has been handled</returns>
6397
6409
protected virtual bool HandleLButtonUp(ref Message m) {
6410
+ // If there are no columns, the base ListView class can throw OutOfRange exceptions.
6411
+ if (this.Columns.Count == 0)
6412
+ return true;
6413
+
6398
6414
if (this.MouseMoveHitTest == null)
6399
6415
return false;
6400
6416
@@ -6446,6 +6462,10 @@ protected virtual bool TriggerGroupExpandCollapse(OLVGroup group)
6446
6462
/// <param name="m">The m to be processed</param>
6447
6463
/// <returns>bool to indicate if the msg has been handled</returns>
6448
6464
protected virtual bool HandleRButtonDown(ref Message m) {
6465
+ // If there are no columns, the base ListView class can throw OutOfRange exceptions.
6466
+ if (this.Columns.Count == 0)
6467
+ return true;
6468
+
6449
6469
int x = m.LParam.ToInt32() & 0xFFFF;
6450
6470
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
6451
6471
@@ -6458,7 +6478,7 @@ protected virtual bool HandleRButtonDown(ref Message m) {
6458
6478
/// <remarks>Subclasses can override this to do something unique</remarks>
6459
6479
/// <param name="hti"></param>
6460
6480
/// <returns>True if the message has been handled</returns>
6461
- protected virtual bool ProcessRButtonDown ( OlvListViewHitTestInfo hti ) {
6481
+ protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) {
6462
6482
if (hti.Item == null)
6463
6483
return false;
6464
6484
@@ -6472,6 +6492,10 @@ protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) {
6472
6492
/// <param name="m">The m to be processed</param>
6473
6493
/// <returns>bool to indicate if the msg has been handled</returns>
6474
6494
protected virtual bool HandleLButtonDoubleClick(ref Message m) {
6495
+ // If there are no columns, the base ListView class can throw OutOfRange exceptions.
6496
+ if (this.Columns.Count == 0)
6497
+ return true;
6498
+
6475
6499
int x = m.LParam.ToInt32() & 0xFFFF;
6476
6500
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
6477
6501
@@ -6485,7 +6509,6 @@ protected virtual bool HandleLButtonDoubleClick(ref Message m) {
6485
6509
/// <param name="hti"></param>
6486
6510
/// <returns>True if the message has been handled</returns>
6487
6511
protected virtual bool ProcessLButtonDoubleClick(OlvListViewHitTestInfo hti) {
6488
-
6489
6512
// If the user double clicked on a checkbox, ignore it
6490
6513
return (hti.HitTestLocation == HitTestLocation.CheckBox);
6491
6514
}
@@ -6496,6 +6519,11 @@ protected virtual bool ProcessLButtonDoubleClick(OlvListViewHitTestInfo hti) {
6496
6519
/// <param name="m">The m to be processed</param>
6497
6520
/// <returns>bool to indicate if the msg has been handled</returns>
6498
6521
protected virtual bool HandleRButtonDoubleClick(ref Message m) {
6522
+
6523
+ // If there are no columns, the base ListView class can throw OutOfRange exceptions.
6524
+ if (this.Columns.Count == 0)
6525
+ return true;
6526
+
6499
6527
int x = m.LParam.ToInt32() & 0xFFFF;
6500
6528
int y = (m.LParam.ToInt32() >> 16) & 0xFFFF;
6501
6529
@@ -6602,7 +6630,7 @@ protected virtual bool HandleReflectNotify(ref Message m) {
6602
6630
//System.Diagnostics.Debug.WriteLine("LVN_GETINFOTIP");
6603
6631
// When virtual lists are in SmallIcon view, they generates tooltip message with invalid item indices.
6604
6632
NativeMethods.NMLVGETINFOTIP nmGetInfoTip = (NativeMethods.NMLVGETINFOTIP)m.GetLParam(typeof(NativeMethods.NMLVGETINFOTIP));
6605
- isMsgHandled = nmGetInfoTip . iItem >= this . GetItemCount ( ) ;
6633
+ isMsgHandled = nmGetInfoTip.iItem >= this.GetItemCount() || this.Columns.Count == 0;
6606
6634
break;
6607
6635
6608
6636
case NM_RELEASEDCAPTURE:
@@ -7804,9 +7832,9 @@ public virtual void UncheckSubItem(object rowObject, OLVColumn column)
7804
7832
/// Return the column at the given index
7805
7833
/// </summary>
7806
7834
/// <param name="index">Index of the column to be returned</param>
7807
- /// <returns>An OLVColumn</returns>
7835
+ /// <returns>An OLVColumn, or null if the index is out of bounds </returns>
7808
7836
public virtual OLVColumn GetColumn(int index) {
7809
- return ( OLVColumn ) this . Columns [ index ] ;
7837
+ return (index >=0 && index < this.Columns.Count) ? ( OLVColumn)this.Columns[index] : null;
7810
7838
}
7811
7839
7812
7840
/// <summary>
@@ -8714,6 +8742,8 @@ protected virtual void PostProcessRows() {
8714
8742
/// Do the work required after one item in a listview have been created
8715
8743
/// </summary>
8716
8744
protected virtual void PostProcessOneRow(int rowIndex, int displayIndex, OLVListItem olvi) {
8745
+ if (this.Columns.Count == 0)
8746
+ return;
8717
8747
if (this.UseAlternatingBackColors && this.View == View.Details && olvi.Enabled) {
8718
8748
olvi.UseItemStyleForSubItems = true;
8719
8749
olvi.BackColor = displayIndex % 2 == 1 ? this.AlternateRowBackColorOrDefault : this.BackColor;
@@ -8882,7 +8912,7 @@ private static void PropagateFormatFromRowToCells(OLVListItem olvi) {
8882
8912
Color backColor = olvi.BackColor;
8883
8913
Color foreColor = olvi.ForeColor;
8884
8914
Font font = olvi.Font;
8885
- foreach ( OLVListSubItem subitem in olvi . SubItems ) {
8915
+ foreach (ListViewItem.ListViewSubItem subitem in olvi.SubItems) {
8886
8916
subitem.BackColor = backColor;
8887
8917
subitem.ForeColor = foreColor;
8888
8918
subitem.Font = font;
@@ -9536,7 +9566,8 @@ public virtual void EditModel(object rowModel) {
9536
9566
return;
9537
9567
9538
9568
for (int i = 0; i < olvItem.SubItems.Count; i++) {
9539
- if ( this . GetColumn ( i ) . IsEditable ) {
9569
+ var olvColumn = this.GetColumn(i);
9570
+ if (olvColumn != null && olvColumn.IsEditable) {
9540
9571
this.StartCellEdit(olvItem, i);
9541
9572
return;
9542
9573
}
@@ -9573,6 +9604,8 @@ public virtual void EditSubItem(OLVListItem item, int subItemIndex) {
9573
9604
/// <param name="subItemIndex">The index of the cell to be edited</param>
9574
9605
public virtual void StartCellEdit(OLVListItem item, int subItemIndex) {
9575
9606
OLVColumn column = this.GetColumn(subItemIndex);
9607
+ if (column == null)
9608
+ return;
9576
9609
Control c = this.GetCellEditor(item, subItemIndex);
9577
9610
Rectangle cellBounds = this.CalculateCellBounds(item, subItemIndex);
9578
9611
c.Bounds = this.CalculateCellEditorBounds(item, subItemIndex, c.PreferredSize);
@@ -10258,7 +10291,7 @@ protected virtual void UpdateHotRow(int rowIndex, int columnIndex, HitTestLocati
10258
10291
if (this.UseHyperlinks) {
10259
10292
OLVColumn column = this.GetColumn(columnIndex);
10260
10293
OLVListSubItem subItem = olvi.GetSubItem(columnIndex);
10261
- if ( column . Hyperlink && hitLocation == HitTestLocation . Text && ! String . IsNullOrEmpty ( subItem . Url ) ) {
10294
+ if (column != null && column .Hyperlink && hitLocation == HitTestLocation.Text && !String.IsNullOrEmpty(subItem.Url)) {
10262
10295
this.ApplyCellStyle(olvi, columnIndex, this.HyperlinkStyle.Over);
10263
10296
this.Cursor = this.HyperlinkStyle.OverCursor ?? Cursors.Default;
10264
10297
} else {
0 commit comments