protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            // If we're on a row, select it.

            e.Handled = true;
            this.Focus();
            dragDecision = MouseDragDecision.NoDecisionMade;

            Point mouseLocationInControl = e.GetPosition(this);
            lastMouseDownPoint = mouseLocationInControl;

            if (availableContentArea.Contains(mouseLocationInControl)) {
                // We're over a row. Apply some selection rules
                int row = RowAtAbsoluteOffset(mouseLocationInControl.Y);

                if (DataSource != null) {

                    if (row < DataSource.NumberOfItemsInTableView(this) && row > -1) {

                        if (Keyboard.Modifiers == ModifierKeys.Control && SelectedRows.Contains(row)) {

                            ArrayList newSelection = new ArrayList(SelectedRows);
                            newSelection.Remove(row);
                            SelectedRows = newSelection;

                        } else if (SelectedRows.Contains(row)) {

                            // In this case, the user either wants to select the single row
                            // OR drag them. Be smart later.

                            selectedRowIfNoDrag = row;

                        } else {

                            if ((Keyboard.Modifiers & ModifierKeys.Control) != 0 && AllowMultipleSelection) {

                                ArrayList newSelection = new ArrayList(SelectedRows);

                                if (Delegate != null) {
                                    if (Delegate.TableViewShouldSelectRow(this, row)) {
                                        newSelection.Add(row);
                                        hingedRow = row;
                                    }
                                } else {
                                    newSelection.Add(row);
                                    hingedRow = row;
                                }

                                SelectedRows = newSelection;

                            } else if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0 && AllowMultipleSelection && SelectedRows.Count > 0 && hingedRow > -1) {

                                // Shift logic

                                // Start at the hinged row, then go select the current row.

                                int maxRow, minRow;

                                if (row > hingedRow) {
                                    minRow = hingedRow;
                                    maxRow = row;
                                } else {
                                    minRow = row;
                                    maxRow = hingedRow;
                                }

                                ArrayList newSelection = new ArrayList();

                                for (int currentRow = minRow; currentRow <= maxRow; currentRow++) {
                                    if (Delegate != null) {
                                        if (Delegate.TableViewShouldSelectRow(this, currentRow)) {
                                            newSelection.Add(currentRow);
                                        }
                                    } else {
                                        newSelection.Add(currentRow);
                                    }
                                }

                                SelectedRows = newSelection;

                            } else {
                                // Replace selection
                                if (Delegate != null) {
                                    if (Delegate.TableViewShouldSelectRow(this, row)) {

                                        ArrayList newSelection = new ArrayList();
                                        newSelection.Add(row);
                                        SelectedRows = newSelection;
                                        hingedRow = row;
                                    }
                                } else {
                                    ArrayList newSelection = new ArrayList();
                                    newSelection.Add(row);
                                    SelectedRows = newSelection;
                                    hingedRow = row;
                                }
                            }
                        }

                    } else {
                        // Clear selection
                        if (Delegate != null) {
                            if (Delegate.TableViewShouldSelectRow(this, row)) {
                                SelectedRows = new ArrayList();
                            }
                        } else {
                            SelectedRows = new ArrayList();
                        }
                    }
                }
            }

            Rect absoluteCellFrame;
            KNCell cell = CellAtAbsolutePoint(mouseLocationInControl, out absoluteCellFrame);

            if (e.RightButton == MouseButtonState.Pressed) {
                if (Delegate != null) {
                    if (Delegate.TableViewDelegateShouldShowContextualMenuWithObjectsAtIndexes(this, SelectedRows)) {
                        selectedRowIfNoDrag = -1;
                        return;
                    }
                }
            }

            this.CaptureMouse();
        }
        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            // Action and reset selectedRowIfNoDrag
            // Reset mouseEventsCell
            e.Handled = true;
            Point mouseLocationInControl = e.GetPosition(this);
            dragDecision = MouseDragDecision.NoDecisionMade;
            this.ReleaseMouseCapture();

            if (selectedRowIfNoDrag > -1) {
                SelectedRows.Clear();
                SelectedRows.Add(selectedRowIfNoDrag);
                selectedRowIfNoDrag = -1;
            }

            // This will update state based on current cursor location
            MouseMoved(e);
        }
        private void MouseDragged(MouseEventArgs e)
        {
            // If the mouse moves over x pixels from the start point
            // and a cell isn't swallowing events, start a drag!
            Point mouseLocationInControl = e.GetPosition(this);

            // We should start a drag. If The delegate allows it, do a proper OS drag.
            // If not, select some rows.

            double verticalMotion = mouseLocationInControl.Y - lastMouseDownPoint.Y;
            double horizontalMotion = mouseLocationInControl.X - lastMouseDownPoint.X;

            if (verticalMotion < 0.0) {
                verticalMotion = 0.0 - verticalMotion;
            }

            if (horizontalMotion < 0.0) {
                horizontalMotion = 0.0 - horizontalMotion;
            }

            if (availableContentArea.Contains(mouseLocationInControl) &&
                (verticalMotion > SystemParameters.MinimumVerticalDragDistance ||
                horizontalMotion > SystemParameters.MinimumHorizontalDragDistance)) {

                if (dragDecision == MouseDragDecision.NoDecisionMade) {

                    if (AllowMultipleSelection) {
                        dragDecision = MouseDragDecision.SelectionDecisionMade;
                    }

                    if (Delegate != null) {

                        // Before asking the delegate, figure out if the drag is up/down
                        // before asking. If up/down, select anyway.

                        if ((horizontalMotion > verticalMotion) || !AllowMultipleSelection) {
                            if (Delegate.TableViewDelegateShouldBeginDragOperationWithObjectsAtIndexes(this, SelectedRows)) {
                                dragDecision = MouseDragDecision.DragDecisionMade;
                                selectedRowIfNoDrag = -1;
                            }
                        }
                    }
                }

                if (dragDecision == MouseDragDecision.SelectionDecisionMade) {

                    int maxAllowableRow = 0;
                    if (DataSource != null) {
                        maxAllowableRow = DataSource.NumberOfItemsInTableView(this);
                    }

                    int row = RowAtAbsoluteOffset(mouseLocationInControl.Y);
                    if (selectedRowIfNoDrag > -1 && selectedRowIfNoDrag <= maxAllowableRow) {
                        hingedRow = selectedRowIfNoDrag;
                        selectedRowIfNoDrag = -1;
                    }

                    int minRow = -1;
                    int maxRow = -1;

                    if (hingedRow < row) {
                        minRow = hingedRow;
                        maxRow = row;
                    } else {
                        minRow = row;
                        maxRow = hingedRow;
                    }

                    if (minRow < 0) {
                        minRow = 0;
                    }

                    if (maxRow > maxAllowableRow) {
                        maxRow = maxAllowableRow;
                    }

                    ArrayList newSelection = new ArrayList();

                    for (int thisRow = minRow; thisRow <= maxRow; thisRow++) {

                        if (Delegate != null) {
                            if (Delegate.TableViewShouldSelectRow(this, thisRow)) {
                                newSelection.Add(thisRow);
                            }
                        } else {
                            newSelection.Add(thisRow);
                        }
                    }

                    SelectedRows = newSelection;
                }

            }
        }