Пример #1
0
        /// <summary>
        /// This is used to select an item in the drop-down as the current item
        /// </summary>
        /// <param name="selIdx">The index of the selected item</param>
        internal void SelectItem(int selIdx)
        {
            dgDropDown.ClearSelection();

            if (selIdx != -1)
            {
                DataGridHelper.ConcedeFocus(dgDropDown);
                dgDropDown.CurrentRowIndex = selIdx;
                dgDropDown.Select(selIdx);
            }
        }
Пример #2
0
        /// <summary>
        /// This can be used to auto-size all columns in the specified <see cref="System.Windows.Forms.DataGrid"/>
        /// control.
        /// </summary>
        /// <param name="dg">The data grid in which to size the columns</param>
        internal static void AutoSizeColumns(DataGrid dg)
        {
            MethodInfo mi = DataGridHelper.DataGridType(dg).GetMethod("ColAutoResize", BindingFlags.NonPublic |
                                                                      BindingFlags.Instance);

            DataGridTableStyle dgs = DataGridHelper.CurrentTableStyle(dg);

            for (int idx = 0; idx < dgs.GridColumnStyles.Count; idx++)
            {
                mi.Invoke(dg, new object[] { idx });
            }
        }
Пример #3
0
        /// <summary>
        /// Highlight the item under the mouse when it moves
        /// </summary>
        /// <param name="e">The event arguments</param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            // We tend to get lots of these even if the mouse doesn't move.  It's an OS thing apparently.
            if (lastMousePos.X != e.X || lastMousePos.Y != e.Y)
            {
                if ((!this.IsSimpleStyle && this.MouseTracking) || e.Button == MouseButtons.Left)
                {
                    lastMousePos = new Point(e.X, e.Y);

                    DataGrid.HitTestInfo hti = base.HitTest(e.X, e.Y);

                    if (hti.Type == DataGrid.HitTestType.Cell)
                    {
                        base.ResetSelection();
                        base.CurrentRowIndex = hti.Row;
                        base.Select(hti.Row);
                    }
                    else
                    if (hti.Type == DataGrid.HitTestType.None)
                    {
                        int newRow = base.CurrentRowIndex;

                        // Scroll when out of bounds
                        if (e.Y < base.Top && newRow > 0)
                        {
                            newRow--;
                        }
                        else
                        if (e.Y > base.Bottom && newRow < DataGridHelper.RowCount(this) - 1)
                        {
                            newRow++;
                        }

                        if (newRow != base.CurrentRowIndex)
                        {
                            base.ResetSelection();
                            base.CurrentRowIndex = newRow;
                            base.Select(newRow);
                        }
                    }
                }

                base.OnMouseMove(e);
            }
        }
Пример #4
0
        /// <summary>
        /// This can be used to force the current edit column in the data grid to concede the focus.  Changes
        /// will be saved if possible.
        /// </summary>
        /// <param name="dg">The data grid to use</param>
        internal static void ConcedeFocus(DataGrid dg)
        {
            Type type = DataGridHelper.DataGridType(dg);

            FieldInfo fi = type.GetField("editColumn", BindingFlags.NonPublic | BindingFlags.Instance);

            dg.EndEdit(null, 0, false);

            DataGridColumnStyle dgc = (DataGridColumnStyle)fi.GetValue(dg);

            if (dgc != null)
            {
                MethodInfo mi = dgc.GetType().GetMethod("ConcedeFocus", BindingFlags.NonPublic |
                                                        BindingFlags.Instance);

                mi.Invoke(dgc, null);
            }
        }
Пример #5
0
 /// <summary>
 /// Scroll the drop-down the specified number of rows
 /// </summary>
 /// <param name="rows">The number of rows to scroll</param>
 public void ScrollDropDown(int rows)
 {
     DataGridHelper.ScrollDown(dgDropDown, rows);
     dgDropDown.Invalidate(true);
 }
Пример #6
0
        /// <summary>
        /// This is used to set the default selected item, size and position the drop-down, and show it
        /// </summary>
        public void ShowDropDown()
        {
            int idx;

            if (!hasInitialized)
            {
                this.CreateHandle();
            }

            idx = startIndex = owner.SelectedIndex;

            dgDropDown.ClearSelection();
            dragOffset = Point.Empty;

            // Sometimes it shows the edit control so clear it
            DataGridHelper.ConcedeFocus(dgDropDown);

            if (idx != -1 && DataGridHelper.RowCount(dgDropDown) > idx)
            {
                dgDropDown.Select(idx);
                dgDropDown.CurrentRowIndex = idx;
            }

            // The owner positions us when using the simple style.  There's also an odd sequence of events
            // related to updates to bound controls that can cause this control to get disposed after setting
            // the data grid's row index above so we'll stop in that case too.
            if (this.IsDisposed || owner.DropDownStyle == ComboBoxStyle.Simple)
            {
                return;
            }

            if (this.Width < owner.Width)
            {
                this.Width = owner.Width;
            }

            // Make sure we are within the screen bounds.  Take into account the working area of all screens.
            // Note that in certain setups, the leftmost/uppermost screen(s) may have negative coordinates.
            Rectangle workingArea, screen = new Rectangle();

            foreach (Screen s in Screen.AllScreens)
            {
                workingArea = s.WorkingArea;

                if (workingArea.X < screen.X)
                {
                    screen.X = workingArea.X;
                }

                if (workingArea.Y < screen.Y)
                {
                    screen.Y = workingArea.Y;
                }

                if (Math.Abs(workingArea.X) + workingArea.Width > screen.Width)
                {
                    screen.Width = Math.Abs(workingArea.X) + workingArea.Width;
                }

                if (Math.Abs(workingArea.Y) + workingArea.Height > screen.Height)
                {
                    screen.Height = Math.Abs(workingArea.Y) + workingArea.Height;
                }
            }

            Point pOwner = owner.Parent.PointToScreen(owner.Location);

            pOwner.Y += owner.Height;

            Point p = pOwner;

            if (this.Width > screen.Width)
            {
                this.Width = screen.Width;
            }

            if (this.Height > screen.Height)
            {
                this.Height = screen.Height;
            }

            if (p.X < screen.X)
            {
                p.X = screen.X;
            }

            if (p.Y < screen.Y)
            {
                p.Y = screen.Y;
            }

            if (p.X + this.Width > screen.X + screen.Width)
            {
                p.X = screen.X + screen.Width - this.Width - 1;
            }

            if (p.Y + this.Height > screen.Y + screen.Height)
            {
                p.Y = screen.Y + screen.Height - this.Height - 1;
            }

            // If we are covering the combo box, move the location above the combo box
            if (p.Y < pOwner.Y)
            {
                idx = pOwner.Y - this.Height - owner.Height;

                // If we would go off the top of the screen, figure out whether we would have more rows visible
                // if we moved the form above the combo box or left it where it is at below the combo box and
                // shrink it to fit.
                if (idx < screen.Y)
                {
                    if (this.Height + idx > this.Height - (pOwner.Y - p.Y))
                    {
                        this.Height += idx;
                        idx          = screen.Y;
                    }
                    else
                    {
                        this.Height -= (pOwner.Y - p.Y);
                        idx          = pOwner.Y;
                    }
                }

                p.Y = idx;
            }

            this.Location = p;

            UnsafeNativeMethods.SetParent(this.Handle, IntPtr.Zero);
            this.Show();

            // NOTE: We lose capture pretty quickly as the mouse isn't inside the drop-down.  MouseLeave grabs it
            // for us again.
            this.Capture = true;
        }
Пример #7
0
        /// <summary>
        /// This is used to initialize the drop-down styles and data source
        /// </summary>
        private void InitDropDown()
        {
            DropDownTableStyle ddts = owner.DropDownFormat;

            int rowCount, rowHeight, headerHeight = 0, idx = 0, totalSize = 0, rowHeaderWidth = ddts.RowHeaderWidth;

            // Must check this before we set the data source otherwise, columns are added by default
            bool autoSize = (ddts.GridColumnStyles.Count == 0);

            dgDropDown.Font        = owner.DropDownFont;
            dgDropDown.RightToLeft = owner.RightToLeft;
            this.BackColor         = dgDropDown.BackgroundColor = owner.DropDownBackColor;
            this.Cursor            = owner.Cursor;

            // Set the data source and apply style settings.  If there is a data source, use it.
            ddts.MappingName      = owner.MappingName;
            dgDropDown.DataMember = owner.BindingPath;

            if (owner.DataSource != null)
            {
                // If bound to a relationship, use the object collection
                if (ddts.MappingName == dgDropDown.DataMember && ddts.MappingName.IndexOf('.') != -1)
                {
                    ddts.MappingName = "ObjectCollection";
                    dgDropDown.TableStyles.Add(ddts);
                    dgDropDown.DataSource = owner.Items;
                }
                else
                {
                    dgDropDown.TableStyles.Add(ddts);
                    dgDropDown.DataSource = owner.DataSource;
                }
            }
            else
            if (ddts.MappingName == "ValueType" || ddts.MappingName == "String")
            {
                // Value and string types require a wrapper or they don't show up correctly
                ValueItem[] viArray = new ValueItem[owner.Items.Count];

                for (int collIdx = 0; collIdx < owner.Items.Count; collIdx++)
                {
                    viArray[collIdx] = new ValueItem(owner.Items[collIdx]);
                }

                ddts.MappingName = "ValueItem[]";
                dgDropDown.TableStyles.Add(ddts);
                dgDropDown.DataSource = viArray;
            }
            else        // It must be an object collection
            {
                dgDropDown.DataSource = owner.Items;
            }

            // Filter the columns if necessary and clear the headers if auto-sizing and they aren't visible.
            // Clearing the header text is necessary so that we get an accurate size.
            StringCollection filter = owner.ColumnFilter;

            if (filter.Count != 0 || (autoSize && !ddts.ColumnHeadersVisible))
            {
                for (idx = 0; idx < ddts.GridColumnStyles.Count; idx++)
                {
                    if (filter.Count != 0 && !filter.Contains(ddts.GridColumnStyles[idx].MappingName))
                    {
                        ddts.GridColumnStyles.RemoveAt(idx);
                        idx--;
                    }
                    else
                    if (autoSize && !ddts.ColumnHeadersVisible)
                    {
                        ddts.GridColumnStyles[idx].HeaderText = String.Empty;
                    }
                }
            }

            // Row Header Width and Column Headers Visible seem to get overridden so restore them
            ddts.RowHeaderWidth             = rowHeaderWidth;
            dgDropDown.ColumnHeadersVisible = ddts.ColumnHeadersVisible;

            // Only auto-size if the user didn't specify any columns
            if (autoSize)
            {
                DataGridHelper.AutoSizeColumns(dgDropDown);
            }

            // Sum the width of the columns and take the opportunity to auto-size columns with a width of zero.
            // This only happens if the user specified column definitions.
            idx = 0;

            foreach (DataGridColumnStyle col in ddts.GridColumnStyles)
            {
                // Replace default null text where needed
                if (col.NullText == "(null)")
                {
                    col.NullText = ddts.DefaultNullText;
                }

                if (col.Width == 0)
                {
                    DataGridHelper.AutoSizeColumn(dgDropDown, idx);
                }

                totalSize += col.Width;
                idx++;
            }

            // Use the specified width or figure out the initial width
            if (owner.DropDownWidth != 0)
            {
                totalSize = owner.DropDownWidth;
            }
            else
            {
                if (ddts.RowHeadersVisible)
                {
                    totalSize += rowHeaderWidth;
                }

                if (idx != 0 && totalSize < owner.Width - 2)
                {
                    // Stretch the last column to fit the width
                    ddts.GridColumnStyles[idx - 1].Width += owner.Width - totalSize - 2;
                    totalSize = owner.Width;
                }
                else
                if (idx == 0)
                {
                    totalSize = owner.Width;
                }
                else
                {
                    totalSize += 2;
                }
            }

            // Enforce a minimum width
            if (totalSize < 30)
            {
                totalSize = 30;
            }

            this.Width = totalSize;

            // Set default height
            rowCount = DataGridHelper.RowCount(dgDropDown);

            if (rowCount != 0 && ddts.GridColumnStyles.Count > 0)
            {
                rowHeight = dgDropDown.GetCellBounds(0, 0).Height + 1;
            }
            else
            {
                rowHeight = dgDropDown.PreferredRowHeight;
            }

            // Figure out column header height if visible.  This is a little ugly but it works.
            if (ddts.ColumnHeadersVisible)
            {
                while (dgDropDown.HitTest(rowHeaderWidth + 2, headerHeight).Type == DataGrid.HitTestType.ColumnHeader)
                {
                    headerHeight++;
                }
            }

            if (rowCount > owner.MaxDropDownItems)
            {
                rowHeight = (rowHeight * owner.MaxDropDownItems) + headerHeight;

                // Adjust width to account for the scrollbar
                this.Width += MultiColumnComboBox.DropDownButtonWidth;
            }
            else
            {
                rowHeight = (rowHeight * rowCount) + headerHeight;
            }

            this.Height    = rowHeight + this.Height - dgDropDown.Height;
            hasInitialized = true;
        }
Пример #8
0
 /// <summary>
 /// Hide any edit control when the grid is scrolled
 /// </summary>
 /// <param name="sender">The sender of the event</param>
 /// <param name="e">The event arguments</param>
 private void DropDownDataGrid_Scroll(object sender, EventArgs e)
 {
     DataGridHelper.ConcedeFocus(this);
 }