예제 #1
0
 /// <summary>
 /// This is in response to focused cell change because of Keyboard navigation.
 /// </summary>
 private void FocusCellChanged()
 {
     this.selectedRanges.Clear();
     this.anchorPoint         = this.ReportGrid.CurrentReportCell.Rect.Center();
     this.currentSelectedCell = this.ReportGrid.CurrentReportCell;
 }
예제 #2
0
        /// <summary>
        /// Handles the mouse button being pressed.
        /// </summary>
        /// <param name="e">The event arguments.</param>
        protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
        {
            // This state variable will control how the 'Mouse Move' and 'Mouse Up' event handlers interpret the user action.  The
            // 'selectedColumn' field is used as the starting point for any drag-and-drop type of operation.
            this.mouseState = MouseState.ButtonDown;

            // Evaluate the state of the keyboard.  Key combinations involving the shift and control keys will alter the areas that
            // are selected.
            bool isShiftKeyPressed   = ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift);
            bool isControlKeyPressed = ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control);

            // The mouse selected with the mouse button is used as an anchor point unless the shift key is pressed.  The anchor
            // point allows for ranges of columns to be selected.  Everything between the anchor and the currently selected column
            // will be selected when the shift key is down.  This is modeled after the Excel extended range selection keys.
            Point mouseDownLocation = e.GetPosition(this);

            // Do not clear the select cells in the Report Grid if the right mouse button is pressed.
            if (e.RightButton != MouseButtonState.Pressed)
            {
                //Since the user is selecting a cell, it will invalidate any row selection that there may be.
                foreach (List <ReportRow> block in this.ReportGrid.SelectedRowBlocks)
                {
                    foreach (ReportRow row in block)
                    {
                        foreach (ReportCell cell in row.Cells)
                        {
                            cell.IsSelected = false;
                        }
                    }
                }
                this.ReportGrid.SelectedRowBlocks.Clear();
                this.ReportGrid.SelectedRowHeaderBlocks.Clear();
            }


            if (!isShiftKeyPressed)
            {
                IInputElement    iInputElement    = this.InputHitTest(mouseDownLocation);
                DependencyObject dependencyObject = iInputElement as DependencyObject;
                while (dependencyObject != null)
                {
                    ReportCell reportCell = DynamicReport.GetCell(dependencyObject);
                    if (reportCell != null)
                    {
                        Keyboard.Focus(dependencyObject as IInputElement);
                        currentSelectedCell = reportCell;
                        break;
                    }
                    dependencyObject = VisualTreeHelper.GetParent(dependencyObject);
                }
                this.anchorPoint = mouseDownLocation;
            }

            // The shift and control key extend the selection operation in the same way as Microsoft Excel.
            if (isShiftKeyPressed || isControlKeyPressed)
            {
                // When the shift key is pressed during column selection, every column between the last column selected
                // and the current column is selected.
                if (isShiftKeyPressed)
                {
                    // This is an ordered rectangle that encompasses all the selected cells.
                    Rect selectedRectangle = GetSelectionRectangle(mouseDownLocation);
                    SetSelectedRectangle(selectedRectangle);
                }

                // When the control key is pressed a single column is added to the range of columns selected.
                if (isControlKeyPressed)
                {
                    // A point marks the range when the control key is pressed.  This is almost identical to pressing the mouse
                    // button except the previous ranges are not cleared.  This is part of the extended selection algorithm that is
                    // modeled after Excel.
                    Rect selectedRange = new Rect(mouseDownLocation, new Size(0, 0));

                    // This removes any previous instance of this column in the selection.
                    foreach (Rect existingRange in this.selectedRanges)
                    {
                        if (selectedRange == existingRange)
                        {
                            this.selectedRanges.Remove(existingRange);
                            break;
                        }
                    }

                    // The new range becomes the starting point for any further extended selection operations.
                    this.selectedRanges.Add(selectedRange);
                }

                // This instructs the event handlers how the mouse movement is to be interpreted.
                this.mouseState = MouseState.Selecting;
            }
            else
            {
                // Evaluate if we need to be able to determine the when we right click within the currently selected range then do not clear the selectedRanges.
                if (!((e.RightButton == MouseButtonState.Pressed) && (CurrentSelectedCell != null) && (CurrentSelectedCell.IsSelected)))                 //MIGHT try this --> if (reportCell.Rect.IntersectsWith(selectedRange))
                {
                    // Clear the selected ranges as we do not have a right mouse button pressed with the currently Selected ranges.

                    // A simple selection that doesn't involve the modifier keys will clear out any previously selected ranges.
                    this.selectedRanges.Clear();
                    // The column is added at the start of a new range of selected columns.
                    this.selectedRanges.Add(new Rect(mouseDownLocation, new Size(0, 0)));
                }
            }


            // Evaluate if we need to be able to determine the when we right click within the currently selected range then do not clear the selectedRanges.
            if (!((e.RightButton == MouseButtonState.Pressed) && (CurrentSelectedCell != null) && (CurrentSelectedCell.IsSelected)))             //MIGHT try this --> if (reportCell.Rect.IntersectsWith(selectedRange))
            {
                // This will select all the columns in the selected ranges of columns and remove the selection from all the rest of the cells.
                SelectCells();
            }
        }
 /// <summary>
 /// Create the event arguments.
 /// </summary>
 /// <param name="row">The row the cell is in.</param>
 /// <param name="cell">The cell itself.</param>
 /// <param name="property">The property that changed.</param>
 public ReportCellPropertyChangedEventArgs(ReportRow row, ReportCell cell, String property)
 {
     this.row      = row;
     this.cell     = cell;
     this.property = property;
 }
예제 #4
0
        /// <summary>
        /// Handles the mouse button being pressed.
        /// </summary>
        /// <param name="e">The event arguments.</param>
        protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
        {
            // This gets the location of the mouse in document coordinates.
            Mouse.Capture(this);

            // This state variable will control how the 'Mouse Move' and 'Mouse Up' event handlers interpret the user action.  The
            // 'selectedColumn' field is used as the starting point for any drag-and-drop type of operation.
            this.mouseState = MouseState.ButtonDown;

            // Evaluate the state of the keyboard.  Key combinations involving the shift and control keys will alter the areas that
            // are selected.
            bool isShiftKeyPressed   = ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift);
            bool isControlKeyPressed = ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control);

            // The mouse selected with the mouse button is used as an anchor point unless the shift key is pressed.  The anchor
            // point allows for ranges of columns to be selected.  Everything between the anchor and the currently selected column
            // will be selected when the shift key is down.  This is modeled after the Excel extended range selection keys.
            this.mouseDownLocation = e.GetPosition(this);
            if (!isShiftKeyPressed)
            {
                this.anchorPoint = this.mouseDownLocation;
            }

            // The mouse indicates which column has been selected and the anchor indicates the starting point of the selection in
            // an extended selection operation.
            ReportColumn selectedColumn = this.ReportGrid.Columns.FindColumnAt(this.mouseDownLocation.X);

            this.anchorColumn = this.ReportGrid.Columns.FindColumnAt(this.anchorPoint.X);

            // Every cell that appears in the header canvas is considered part of the selectable header.  This will collect all the
            // selected cells in a list while creating a rectangle that is the union of all those selected cells.
            this.headerCells.Clear();
            foreach (ReportRow reportRow in this.ReportGrid.Rows)
            {
                ReportCell reportCell = reportRow[this.anchorColumn];
                if (reportRow.Top < this.ActualHeight)
                {
                    this.headerCells.Add(reportCell);
                }
            }

            // Every cell that appears in the header canvas is considered part of the selectable header.  This will collect all the
            // selected cells in a list while creating a rectangle that is the union of all those selected cells.
            Rect selectedRect = this.headerCells[0].Rect;

            for (int index = 1; index < this.headerCells.Count; index++)
            {
                selectedRect = Rect.Union(selectedRect, this.headerCells[index].Rect);
            }

            // If a column is selected then the position and movement of the mouse will suggest one of several gestures that need
            // to be interpreted: is a column being moved, is it being resized, is it being deleted or selected?  The code below
            // will begin to interpret the input gesture.
            if (selectedColumn != null)
            {
                // The header has two modes: when the headers are frozen, only selection operations are enabled with the mouse.
                // When not frozen, the columns can be moved, resized, resorted and removed.
                if (this.IsHeaderFrozen)
                {
                    // The shift and control key extend the selection operation in the same way as Microsoft Excel.
                    if (isShiftKeyPressed || isControlKeyPressed)
                    {
                        // When the shift key is pressed during column selection, every column between the last column selected
                        // and the current column is selected.
                        if (isShiftKeyPressed)
                        {
                            // In the unlikely event that the shift key was down during the setting of the anchor point, this will
                            // create a dummy entry in the list of selected column ranges.
                            if (this.selectedRanges.Count == 0)
                            {
                                List <ReportColumn> reportColumns = new List <ReportColumn>();
                                reportColumns.Add(selectedColumn);
                                this.selectedRanges.Add(reportColumns);
                            }

                            // The most recent range will be replaced with a new range when the mouse is dragged around the column
                            // headers.  This has the effect of clearing the columns that are no longer selected and selecting only
                            // the columns between the anchor and the currently selected column.
                            List <ReportColumn> lastRange = this.selectedRanges[this.selectedRanges.Count - 1];
                            int firstIndex  = this.ReportGrid.Columns.IndexOf(this.anchorColumn);
                            int secondIndex = this.ReportGrid.Columns.IndexOf(selectedColumn);
                            int startIndex  = firstIndex < secondIndex ? firstIndex : secondIndex;
                            int endIndex    = firstIndex > secondIndex ? firstIndex : secondIndex;

                            // This will replace the last range in the list with the new range selected from the current position
                            // and the anchor position.
                            lastRange.Clear();
                            for (int index = startIndex; index <= endIndex; index++)
                            {
                                lastRange.Add(this.ReportGrid.Columns[index] as ReportColumn);
                            }
                        }

                        // When the control key is pressed a single column is added to the range of columns selected.
                        if (isControlKeyPressed)
                        {
                            // This removes any previous instance of this column in the selection.
                            foreach (List <ReportColumn> columnRange in this.selectedRanges)
                            {
                                if (columnRange.Contains(selectedColumn))
                                {
                                    columnRange.Remove(selectedColumn);
                                }
                            }

                            // The column is added (or re-added) at the start of the range of selected columns.
                            List <ReportColumn> reportColumns = new List <ReportColumn>();
                            reportColumns.Add(selectedColumn);
                            this.selectedRanges.Add(reportColumns);
                        }
                    }
                    else
                    {
                        // A simple selection that doesn't involve the modifier keys will clear out any previously selected ranges.
                        selectedRanges.Clear();

                        // The column is added at the start of a new range of selected columns.
                        List <ReportColumn> reportColumns = new List <ReportColumn>();
                        reportColumns.Add(selectedColumn);
                        this.selectedRanges.Add(reportColumns);
                    }

                    // This will select all the columns in the selected ranges of columns and remove the selection from all the
                    // rest of the cells.
                    SelectCells();

                    // This instructs the event handlers how the mouse movement is to be interpreted.
                    this.mouseState = MouseState.Selecting;
                }
                else
                {
                    // The left mouse button can either select the column or begin a resizing operation.  This will perform a 'Hit
                    // Test' to see which operation should be performed.
                    if (e.LeftButton == MouseButtonState.Pressed)
                    {
                        // This is a 'Hit Test' for the right edge of the column header tile to see if the user is trying to
                        // change the size of the column.  If the mouse is close to the right edge, then the drag operation to
                        // change the size of the tile is begun.
                        if (selectedColumn.Right - DynamicReport.splitBorder <= this.mouseDownLocation.X &&
                            this.mouseDownLocation.X < selectedColumn.Right)
                        {
                            this.resizeStart       = selectedColumn.Right;
                            this.mouseState        = MouseState.ResizingColumn;
                            this.destinationColumn = null;
                        }
                        else
                        {
                            // This is a 'Hit Test' for the left edge of the column header tile to see if the user is trying to
                            // change the size of the column.  Note that because the left edge really belongs to the previous
                            // column header when resizing, that the previous column is selected for the operation.
                            if (selectedColumn.Left <= this.mouseDownLocation.X &&
                                this.mouseDownLocation.X < selectedColumn.Left + DynamicReport.splitBorder)
                            {
                                this.resizeStart = selectedColumn.Left;
                                this.mouseState  = MouseState.ResizingColumn;
                                int index = this.ReportGrid.Columns.IndexOf(selectedColumn);
                                if (index != 0)
                                {
                                    this.anchorColumn      = this.ReportGrid.Columns[index - 1] as ReportColumn;
                                    this.destinationColumn = null;
                                }
                            }
                        }
                    }

                    // At this point, a resizing operation has been selected from the input gesture of the mouse.
                    if (this.mouseState == MouseState.ResizingColumn)
                    {
                        // The parent window will watch for this event to tell it how to draw the column width indicator lines. The
                        // dimension and location of those lines are outside of this window and must be handled by the parent.
                        if (this.ResizeMouseMove != null)
                        {
                            this.ResizeMouseMove(this, new ResizeColumnEventArgs(this.anchorColumn, this.anchorColumn.Width,
                                                                                 false));
                        }

                        // This window provides quantitative feedback for the new width of the column.  The offsets were arrived at
                        // empirically from reverse engineering Excel.
                        this.columnWidthPopup.HorizontalOffset = this.mouseDownLocation.X - 2.0;
                        this.columnWidthPopup.Content          = selectedColumn.Width;
                        this.columnWidthPopup.IsOpen           = true;
                    }
                    else
                    {
                        // This will select the button momentarily for drag-and-drop and sorting operations.
                        foreach (ReportCell reportCell in this.headerCells)
                        {
                            reportCell.IsSelected = true;
                        }
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Handles the mouse button being pressed.
        /// </summary>
        /// <param name="e">The event arguments.</param>
        protected override void OnMouseDown(System.Windows.Input.MouseButtonEventArgs e)
        {
            // The sort order is maintained in this structure.
            this.sortOrder = new List <SortItem>();

            // This gets the location of the mouse in document coordinates.
            Mouse.Capture(this);

            // This state variable will control how the 'Mouse Move' and 'Mouse Up' event handlers interpret the user action.  The
            // 'selectedRow' field is used as the starting point for any drag-and-drop type of operation.
            this.mouseState = MouseState.ButtonDown;

            // Evaluate the state of the keyboard.  Key combinations involving the shift and control keys will alter the areas that
            // are selected.
            bool isShiftKeyPressed   = ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift);
            bool isControlKeyPressed = ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control);

            // This will use the current position for an anchor unless the shift key is pressed.
            this.mouseDownLocation = e.GetPosition(this);
            if (!isShiftKeyPressed)
            {
                this.anchorPoint = this.mouseDownLocation;
            }

            // The mouse indicates which column has been selected and the anchor indicates the starting point of the selection in
            // an extended selection operation.
            ReportRow selectedRow = this.ReportGrid.Rows.FindRowAt(this.mouseDownLocation.Y);
            ReportRow anchorRow   = this.ReportGrid.Rows.FindRowAt(this.anchorPoint.Y);

            Point mouseDownLocation = e.GetPosition(this);

            if (!isShiftKeyPressed)
            {
                IInputElement    iInputElement    = this.InputHitTest(mouseDownLocation);
                DependencyObject dependencyObject = iInputElement as DependencyObject;
                while (dependencyObject != null)
                {
                    if (DynamicReport.GetCell(dependencyObject) != null)
                    {
                        Keyboard.Focus(dependencyObject as IInputElement);
                        break;
                    }
                    dependencyObject = VisualTreeHelper.GetParent(dependencyObject);
                }
            }

            // Every cell that appears in the header canvas is considered part of the selectable header.  This will collect all the
            // selected cells in a list while creating a rectangle that is the union of all those selected cells.
            this.headerCells.Clear();
            foreach (ReportColumn reportColumn in this.ReportGrid.Columns)
            {
                ReportCell reportCell = selectedRow[reportColumn];
                if (reportColumn.Left < this.ActualWidth)
                {
                    this.headerCells.Add(reportCell);
                }
            }

            // If a row is selected then the position and movement of the mouse will suggest one of several gestures that need
            // to be interpreted: is a row being moved, is it being resized, is it being deleted or selected?  The code below
            // will begin to interpret the input gesture.
            if (selectedRow != null)
            {
                // The header has two modes: when the headers are frozen, only selection operations are enabled with the mouse.
                // When not frozen, the rows can be moved, resized, resorted and removed.
                if (this.IsHeaderFrozen)
                {
                    // The shift and control key extend the selection operation in the same way as Microsoft Excel.
                    if (isShiftKeyPressed || isControlKeyPressed)
                    {
                        // When the shift key is pressed during row selection, every row between the last row selected
                        // and the current row is selected.
                        if (isShiftKeyPressed)
                        {
                            // In the unlikely event that the shift key was down during the setting of the anchor point, this will
                            // create a dummy entry in the list of selected row ranges.
                            if (this.selectedRanges.Count == 0)
                            {
                                List <ReportRow> reportRows = new List <ReportRow>();
                                reportRows.Add(selectedRow);
                                this.selectedRanges.Add(reportRows);
                            }

                            // The most recent range will be replaced with a new range when the mouse is dragged around the row
                            // headers.  This has the effect of clearing the rows that are no longer selected and selecting only
                            // the rows between the anchor and the currently selected row.
                            List <ReportRow> lastRange = this.selectedRanges[this.selectedRanges.Count - 1];

                            // This will select each row between the last selected row and the one just selected.  Note that the
                            // list of rows is distinct, so duplicate rows are ignored.
                            ReportRow firstRow  = anchorRow.Top < selectedRow.Top ? anchorRow : selectedRow;
                            ReportRow secondRow = anchorRow.Top < selectedRow.Top ? selectedRow : anchorRow;
                            lastRange.Clear();
                            foreach (ReportRow reportRow in this.ReportGrid.Rows)
                            {
                                if (firstRow.Top <= reportRow.Top && reportRow.Top <= secondRow.Top)
                                {
                                    lastRange.Add(reportRow);
                                }
                            }
                        }

                        // When the control key is pressed a single row is added to the range of rows selected.
                        if (isControlKeyPressed)
                        {
                            // This removes any previous instance of this row in the selection.
                            foreach (List <ReportRow> rowRange in this.selectedRanges)
                            {
                                if (rowRange.Contains(selectedRow))
                                {
                                    rowRange.Remove(selectedRow);
                                }
                            }

                            // The row is added (or re-added) at the start of the range of selected rows.
                            List <ReportRow> reportRows = new List <ReportRow>();
                            reportRows.Add(selectedRow);
                            this.selectedRanges.Add(reportRows);
                        }
                    }
                    else
                    {
                        // The row is added at the start of a new range of selected rows.
                        List <ReportRow> reportRows = new List <ReportRow>();

                        // The if condition below fixes issue that allows the right click to not clear the selected rows.
                        // Hence it allows every other condition to clear the state.
                        if (e.RightButton != MouseButtonState.Pressed)
                        {
                            // A simple selection that doesn't involve the modifier keys will clear out any previously selected ranges.
                            this.selectedRanges.Clear();
                        }
                        else
                        {
                            // This removes any previous instance of this row in the selection.
                            foreach (List <ReportRow> rowRange in this.selectedRanges)
                            {
                                if (rowRange.Contains(selectedRow))
                                {
                                    rowRange.Remove(selectedRow);
                                }
                            }
                        }

                        reportRows.Add(selectedRow);
                        this.selectedRanges.Add(reportRows);
                    }

                    // This will select all the rows in the selected ranges of rows and remove the selection from all the
                    // rest of the cells.
                    SelectRows();

                    // This instructs the event handlers how the mouse movement is to be interpreted.
                    this.mouseState = MouseState.Selecting;
                }
                else
                {
                    // The top mouse button can either select the row or begin a resizing operation.  This will perform a 'Hit
                    // Test' to see which operation should be performed.
                    if (e.LeftButton == MouseButtonState.Pressed)
                    {
                        // This is a 'Hit Test' for the bottom edge of the row header tile to see if the user is trying to change
                        // the size of the row.  If the mouse is close to the bottom edge, then the drag operation to change the
                        // size of the tile is begun.
                        if (selectedRow.Bottom - DynamicReport.splitBorder <= this.mouseDownLocation.Y &&
                            this.mouseDownLocation.Y < selectedRow.Bottom)
                        {
                            this.resizeStart    = selectedRow.Bottom;
                            this.mouseState     = MouseState.ResizingRow;
                            this.destinationRow = null;
                        }
                        else
                        {
                            // This is a 'Hit Test' for the top edge of the row header tile to see if the user is trying to change
                            // the size of the row.  Note that because the top edge really belongs to the previous row header when
                            // resizing, that the previous row is selected for the operation.
                            if (selectedRow.Top <= this.mouseDownLocation.Y &&
                                this.mouseDownLocation.Y < selectedRow.Top + DynamicReport.splitBorder)
                            {
                                this.resizeStart = selectedRow.Top;
                                this.mouseState  = MouseState.ResizingRow;
                                foreach (ReportRow reportRow in this.ReportGrid.Rows)
                                {
                                    if (reportRow.Bottom == selectedRow.Top)
                                    {
                                        selectedRow = reportRow;
                                    }
                                }
                                this.destinationRow = null;
                            }
                        }
                    }

                    // At this point, a resizing operation has been selected from the input gesture of the mouse.
                    if (this.mouseState == MouseState.ResizingRow)
                    {
                        // The parent window will watch for this event to tell it how to draw the row width indicator lines. The
                        // dimension and location of those lines are outside of this window and must be handled by the parent.
                        if (this.ResizeMouseMove != null)
                        {
                            this.ResizeMouseMove(this, new ResizeRowEventArgs(selectedRow, selectedRow.Height,
                                                                              false));
                        }

                        // This window provides quantitative feedback for the new width of the row.  The offsets were arrived at
                        // empirically from reverse engineering Excel.
                        this.rowHeightPopup.VerticalOffset = this.mouseDownLocation.Y - 2.0;
                        this.rowHeightPopup.Content        = selectedRow.Height;
                        this.rowHeightPopup.IsOpen         = true;
                    }
                    else
                    {
                        // This will select the button momentarily for drag-and-drop and sorting operations.
                        foreach (ReportCell reportCell in this.headerCells)
                        {
                            reportCell.IsSelected = true;
                        }
                    }
                }
            }
        }