/// <summary> /// Switch the selection column. For multiselect, the behavior is highly dependent on the /// the ColumnSelectionTransferAction property and the prior state of the permutation, if /// the permutation is being reordered /// </summary> /// <param name="column">The new selection column</param> /// <param name="oldPermutation">The old column permuation</param> /// <param name="fireEvents">True if this routine should fire selection events</param> private void SetSelectionColumn(int column, ColumnPermutation oldPermutation, bool fireEvents) { Debug.Assert(oldPermutation != null || column != mySelectionColumn); var iCaret = CurrentIndex; DismissLabelEdit(false, false); var oldColumn = mySelectionColumn; mySelectionColumn = column; if (GetStyleFlag(VTCStyleFlags.MultiSelect)) { switch (myColumnSelectionAction) { case ColumnSelectionTransferAction.PreserveNonBlankCells: SetSelectionColumn_PreserveBasic(oldColumn, oldPermutation, column, false, fireEvents); break; case ColumnSelectionTransferAction.PreserveAnchoredCells: SetSelectionColumn_PreserveBasic(oldColumn, oldPermutation, column, true, fireEvents); break; case ColumnSelectionTransferAction.PreserveSharedAnchors: SetSelectionColumn_PreserveAnchors(oldColumn, oldPermutation, column, false, fireEvents); break; case ColumnSelectionTransferAction.PreserveSharedAnchorsOnly: SetSelectionColumn_PreserveAnchors(oldColumn, oldPermutation, column, true, fireEvents); break; case ColumnSelectionTransferAction.ClearSelectedRows: SetSelectionColumn_Clear(fireEvents); break; } } else if (iCaret != -1 && fireEvents) { CurrentIndex = iCaret; } if (oldColumn != mySelectionColumn) { // This may cause a focus change, because the caret moves to a different column. if (!GetStateFlag(VTCStateFlags.RestoringSelection) && VirtualTreeAccEvents.ShouldNotify(VirtualTreeAccEvents.eventObjectFocus, this) && Focused) { VirtualTreeAccEvents.Notify( VirtualTreeAccEvents.eventObjectFocus, CurrentIndex, CurrentColumn, this); } // ensure newly selected column is scrolled into view. if (HasHorizontalScrollBar) { ScrollColumnIntoView(CurrentColumn); } // make sure we invalidate the caret item if (CurrentIndex != VirtualTreeConstant.NullIndex) { InvalidateItem(CurrentIndex, -1, NativeMethods.RedrawWindowFlags.Invalidate); } } }
/// <summary> /// Fires WinEvents for given selection change. /// </summary> private void FireWinEventsForSelection(bool extendFromAnchor, bool preserveSelection, ModifySelectionAction caretAction) { if (GetStateFlag(VTCStateFlags.RestoringSelection)) { return; // no events if we're restoring selection. } if (SelectionCount == 1) { // if there's currently only one thing selected, we know we should fire a regular selection event. if (VirtualTreeAccEvents.ShouldNotify(VirtualTreeAccEvents.eventObjectSelection, this)) { VirtualTreeAccEvents.Notify( VirtualTreeAccEvents.eventObjectSelection, CurrentIndex, CurrentColumn, this); } } else if (extendFromAnchor) { if (VirtualTreeAccEvents.ShouldNotify(VirtualTreeAccEvents.eventObjectSelectionWithin, this)) { // we extended selection from the anchor position, this constitutes a significant change in selection // state, so we fire selection within from the tree control, and let clients query us for the result. // UNDONE: querying currently won't work because we need a way to return an IEnumVariant from IAccessible::get_accSelection. // We just fire selection for the caret instead. // VirtualTreeAccEvents.Notify(VirtualTreeAccEvents.eventObjectSelectionWithin, VirtualTreeConstant.NullIndex, // VirtualTreeConstant.NullIndex, this); VirtualTreeAccEvents.Notify( VirtualTreeAccEvents.eventObjectSelection, CurrentIndex, CurrentColumn, this); } } else if (preserveSelection) { // we're preserving an original selection, which means that we fire either an add or a remove, // depending on what happened to the caret switch (caretAction) { case ModifySelectionAction.Select: if (VirtualTreeAccEvents.ShouldNotify(VirtualTreeAccEvents.eventObjectSelectionAdd, this)) { VirtualTreeAccEvents.Notify( VirtualTreeAccEvents.eventObjectSelectionAdd, CurrentIndex, CurrentColumn, this); } break; case ModifySelectionAction.Clear: if (VirtualTreeAccEvents.ShouldNotify(VirtualTreeAccEvents.eventObjectSelectionRemove, this)) { VirtualTreeAccEvents.Notify( VirtualTreeAccEvents.eventObjectSelectionRemove, CurrentIndex, CurrentColumn, this); } break; case ModifySelectionAction.Toggle: if (IsSelected(CaretIndex)) { goto case ModifySelectionAction.Select; } else { goto case ModifySelectionAction.Clear; } case ModifySelectionAction.None: // Caret position didn't change, but selection still changed overall. This happens, for instance, // during cross-column selection transfer. We would ideally fire selection within here, for now // we just fire selection at the caret position anyway. if (VirtualTreeAccEvents.ShouldNotify(VirtualTreeAccEvents.eventObjectSelectionWithin, this)) { //VirtualTreeAccEvents.Notify(VirtualTreeAccEvents.eventObjectSelectionWithin, VirtualTreeConstant.NullIndex, // VirtualTreeConstant.NullIndex, this); VirtualTreeAccEvents.Notify( VirtualTreeAccEvents.eventObjectSelection, CurrentIndex, CurrentColumn, this); } break; } } }