无法访问已处置的对象。对象名称:'NumericUpDown'

时间:2013-07-01 13:52:49

标签: c# .net winforms

我创建了一个DatagridViewNumericUpDownColumn,它实际上是一个自定义控件,但是当我关闭并重新打开表单时收到错误消息:

  

无法访问已处置的对象。对象名称:'NumericUpDown'

我正在为numericupdown编写以下代码

[ThreadStatic]
        private static NumericUpDown paintingNumericUpDown; 

 protected override void Paint(Graphics graphics, Rectangle clipBounds, Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState,
                                      object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle,
                                      DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
            try
            {
                if (this.DataGridView == null)
                {
                    return;
                }

                // First paint the borders and background of the cell.
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle,
                           paintParts & ~(DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.ContentForeground));

                Point ptCurrentCell = this.DataGridView.CurrentCellAddress;
                bool cellCurrent = ptCurrentCell.X == this.ColumnIndex && ptCurrentCell.Y == rowIndex;
                bool cellEdited = cellCurrent && this.DataGridView.EditingControl != null;

                // If the cell is in editing mode, there is nothing else to paint
                if (!cellEdited)
                {
                    if (PartPainted(paintParts, DataGridViewPaintParts.ContentForeground))
                    {
                        // Paint a NumericUpDown control
                        // Take the borders into account
                        Rectangle borderWidths = BorderWidths(advancedBorderStyle);
                        Rectangle valBounds = cellBounds;
                        valBounds.Offset(borderWidths.X, borderWidths.Y);
                        valBounds.Width -= borderWidths.Right;
                        valBounds.Height -= borderWidths.Bottom;
                        // Also take the padding into account
                        if (cellStyle.Padding != Padding.Empty)
                        {
                            if (this.DataGridView.RightToLeft == RightToLeft.Yes)
                            {
                                valBounds.Offset(cellStyle.Padding.Right, cellStyle.Padding.Top);
                            }
                            else
                            {
                                valBounds.Offset(cellStyle.Padding.Left, cellStyle.Padding.Top);
                            }
                            valBounds.Width -= cellStyle.Padding.Horizontal;
                            valBounds.Height -= cellStyle.Padding.Vertical;
                        }
                        // Determine the NumericUpDown control location
                        valBounds = GetAdjustedEditingControlBounds(valBounds, cellStyle);

                        bool cellSelected = (cellState & DataGridViewElementStates.Selected) != 0;

                        if (renderingBitmap.Width < valBounds.Width ||
                            renderingBitmap.Height < valBounds.Height)
                        {
                            // The static bitmap is too small, a bigger one needs to be allocated.
                            renderingBitmap.Dispose();
                            renderingBitmap = new Bitmap(valBounds.Width, valBounds.Height);
                        }
                        // Make sure the NumericUpDown control is parented to a visible control
                        if (paintingNumericUpDown.Parent == null || !paintingNumericUpDown.Parent.Visible)
                        {
                            paintingNumericUpDown.Parent = this.DataGridView;
                        }
                        // Set all the relevant properties
                        paintingNumericUpDown.TextAlign = DataGridViewNumericUpDownCell.TranslateAlignment(cellStyle.Alignment);
                        paintingNumericUpDown.DecimalPlaces = this.DecimalPlaces;
                        paintingNumericUpDown.ThousandsSeparator = this.ThousandsSeparator;
                        paintingNumericUpDown.Font = cellStyle.Font;
                        paintingNumericUpDown.Width = valBounds.Width;
                        paintingNumericUpDown.Height = valBounds.Height;
                        paintingNumericUpDown.RightToLeft = this.DataGridView.RightToLeft;
                        paintingNumericUpDown.Location = new Point(0, -paintingNumericUpDown.Height - 100);
                        paintingNumericUpDown.Text = formattedValue as string;

                        Color backColor;
                        if (PartPainted(paintParts, DataGridViewPaintParts.SelectionBackground) && cellSelected)
                        {
                            backColor = cellStyle.SelectionBackColor;
                        }
                        else
                        {
                            backColor = cellStyle.BackColor;
                        }
                        if (PartPainted(paintParts, DataGridViewPaintParts.Background))
                        {
                            if (backColor.A < 255)
                            {
                                // The NumericUpDown control does not support transparent back colors
                                backColor = Color.FromArgb(255, backColor);
                            }
                            paintingNumericUpDown.BackColor = backColor;
                        }
                        // Finally paint the NumericUpDown control
                        Rectangle srcRect = new Rectangle(0, 0, valBounds.Width, valBounds.Height);
                        if (srcRect.Width > 0 && srcRect.Height > 0)
                        {
                            paintingNumericUpDown.DrawToBitmap(renderingBitmap, srcRect);
                            graphics.DrawImage(renderingBitmap, new Rectangle(valBounds.Location, valBounds.Size),
                                               srcRect, GraphicsUnit.Pixel);
                        }
                    }
                    if (PartPainted(paintParts, DataGridViewPaintParts.ErrorIcon))
                    {
                        // Paint the potential error icon on top of the NumericUpDown control
                        base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText,
                                   cellStyle, advancedBorderStyle, DataGridViewPaintParts.ErrorIcon);
                    }
                }
            }
            catch 
            {
                throw;
            }
        }

这个问题有解决办法吗?

3 个答案:

答案 0 :(得分:1)

这种情况正在发生,因为这些事件在处理表单时仍然被触发(即关闭表单),所以你只需要这一行:

if (paintingNumericUpDown.IsDisposed) { return; }

位于方法的顶部。这是做自己绘画的副产品。

答案 1 :(得分:0)

解决它的最简单的方法我认为在catch部分不抛出,但如果需要则执行new NumericUpDown()。另一种方法是在处置

时不处理NumericUpDown或执行new NumericUpDown()

答案 2 :(得分:0)

从此处使用Microsoft的代码时,我遇到了类似的问题:https://docs.microsoft.com/en-us/previous-versions/aa730881(v=vs.80)

我想您基于此示例的解决方案,因此您的构造函数中包含以下内容:

        // Create a thread specific NumericUpDown control used for the painting of the non-edited cells
        if (paintingNumericUpDown == null)
        {
            paintingNumericUpDown = new NumericUpDown();
            // Some properties only need to be set once for the lifetime of the control:
            paintingNumericUpDown.BorderStyle = BorderStyle.None;
            paintingNumericUpDown.Maximum = Decimal.MaxValue / 10;
            paintingNumericUpDown.Minimum = Decimal.MinValue / 10;
        }

我通过更频繁地重新创建paintedNumericUpDown解决了我的问题:

        // Create a thread specific NumericUpDown control used for the painting of the non-edited cells
        if (paintingNumericUpDown == null || paintingNumericUpDown.IsDisposed)
        {
            paintingNumericUpDown = new NumericUpDown();
            // Some properties only need to be set once for the lifetime of the control:
            paintingNumericUpDown.BorderStyle = BorderStyle.None;
            paintingNumericUpDown.Maximum = Decimal.MaxValue / 10;
            paintingNumericUpDown.Minimum = Decimal.MinValue / 10;
        }

我希望对您也有用。