добавить пользовательский DataGridViewColumn с меткой и кнопкой для каждой ячейки - PullRequest
0 голосов
/ 08 ноября 2018

Я хочу добавить пользовательский DataGridViewColumn к моему DataGridView.Этот столбец должен создать следующую ячейку в строке

img

Сначала я создал пользовательский UserControl, который создает ярлык с кнопкой.

    private class AllocationControl : UserControl
    {
        public AllocationControl(IndexField[] indexFields, BatchField[] batchFields)
        {
            Label lbl = new Label();
            Controls.Add(lbl);

            ContextMenuStrip contextMenu = new ContextMenuStrip();
            // fill the menu
            Controls.Add(contextMenu);

            Button btn = new Button();
            btn.Click += (object sender, EventArgs e) =>
            {
                contextMenu.Show(Cursor.Position);
            };
            Controls.Add(btn);
        }

        public string DisplayedName { get; private set; }
        public double SelectedID { get; private set; }
    }

Я должен передать некоторые данные в качестве параметров конструктора, но это не имеет отношения к вопросу.

После этого я создаю пользовательский DataGridViewCell

    private class DataGridViewAllocationCell : DataGridViewCell
    {
        public DataGridViewAllocationCell()
        {
        }

        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)
        {
            AllocationControl allocationControl = value as AllocationControl;
            Bitmap allocationControlImage = new Bitmap(cellBounds.Width, cellBounds.Height);
            allocationControl.DrawToBitmap(allocationControlImage, new Rectangle(0, 0, allocationControl.Width, allocationControl.Height));
            graphics.DrawImage(allocationControlImage, cellBounds.Location);
        }
    }

Этоячейка должна сохранять пользовательский элемент управления и отображать его.

В конце я добавляю эту ячейку к своему пользовательскому DataGridViewColumn, устанавливая CellTemplate

    private class DataGridViewAllocationColumn : DataGridViewColumn
    {
        public DataGridViewAllocationColumn()
        {
            CellTemplate = new DataGridViewAllocationCell();
        }
    }

Мой вопрос, как я могуназначьте UserControl на DataGridViewCell?

Я взял это руководство

https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-host-controls-in-windows-forms-datagridview-cells

, но все они показывают, как создать один элемент управления и поместить егов клетку.Мне нужно настроить три элемента управления (метка, кнопка и contextMenu) в одной ячейке.

1 Ответ

0 голосов
/ 13 ноября 2018

Существует 3 основных столпа для нового типа столбца:

  • DataGridViewColumn отвечает за свойства, которые вы задали в режиме конструктора в редакторе столбцов элемента управления.
  • DataGridViewCell отвечает за внешний вид ячейки.Он отображает значение и другие детали рисования в ячейке и инициализирует элемент управления для редактирования (если столбец имеет какой-либо элемент управления для редактирования).
  • DataGridViewEditingControl отвечает за редактирование значения ячейки.

При создании нового столбца вы можете наследовать от DataGridViewColumn или одного из его производных классов.Также при создании новой ячейки для столбца вы можете получить из DataGridViewCell или одного из его производных классов.Кроме того, при создании нового элемента управления для редактирования вы можете извлечь из одного из существующих элементов управления для редактирования или начать с создания класса управления и реализации интерфейса IDataGridViewEditingControl.

Имейте в виду, что элемент управления редактирования будетбыть показано только в ячейке редактирования.Остальные ячейки показывают, что вы визуализируете в методе рисования ячейки.

Пример

Здесь, в этом посте, я поделился примером рисования пользовательской ячейкисодержащий ярлык и кнопку.Я не создал элемент управления для редактирования, потому что для этого примера мы можем получить производные от DataGridViewButtonColumn и DataGridViewButtonCell без необходимости создания элемента управления для редактирования.Мы просто добавляем некоторые свойства в столбец и меняем логику рисования и переопределяем OnContentClick, чтобы отобразить контекстное меню, например:

enter image description here

Пользовательский столбец имеетLabelText и ButtonText свойства.При нажатии на часть кнопки отображается ContextMenuStrip, который вы присвоили соответствующему свойству.

Примечание: Это всего лишь пример, и в зависимости от требований выможет потребоваться изменить свойства, логику рендеринга и способ отображения меню или что-либо еще.Но я думаю, что это хорошая отправная точка.

Вот код:

using System.Drawing;
using System.Windows.Forms;
public class DataGridViewAllocationControlColumn : DataGridViewButtonColumn
{
    public DataGridViewAllocationControlColumn()
    {
        this.CellTemplate = new DataGridViewAllocationControlCell();
    }
    public string LabelText { get; set; }
    public string ButtonText { get; set; }
    public override object Clone()
    {
        var c = (DataGridViewAllocationControlColumn)base.Clone();
        c.LabelText = this.LabelText;
        c.ButtonText = this.ButtonText;
        return c;
    }
}
public class DataGridViewAllocationControlCell : DataGridViewButtonCell
{
    protected override void Paint(Graphics graphics, Rectangle clipBounds,
        Rectangle cellBounds, int rowIndex, 
        DataGridViewElementStates elementState,
        object value, object formattedValue, string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        var g = this.DataGridView;
        var c = (DataGridViewAllocationControlColumn)this.OwningColumn;
        base.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState,
            value, formattedValue, errorText, cellStyle, advancedBorderStyle,
            DataGridViewPaintParts.All &
            ~DataGridViewPaintParts.ContentBackground &
            ~DataGridViewPaintParts.ContentForeground);
        var r1 = g.GetCellDisplayRectangle(c.Index, rowIndex, false);
        var r2 = GetContentBounds(rowIndex);
        var r3 = new Rectangle(r1.Location, new Size(GetLabelWidth(), r1.Height));
        r2.Offset(r1.Location);
        base.Paint(graphics, clipBounds, r2, rowIndex, elementState,
            value, c.ButtonText, errorText, cellStyle, advancedBorderStyle,
            DataGridViewPaintParts.All);
        TextRenderer.DrawText(graphics, c.LabelText, cellStyle.Font,
            r3, cellStyle.ForeColor);
    }
    protected override Rectangle GetContentBounds(Graphics graphics, 
        DataGridViewCellStyle cellStyle, int rowIndex)
    {
        var w = GetLabelWidth();
        var r = base.GetContentBounds(graphics, cellStyle, rowIndex);
        return new Rectangle(r.Left + w, r.Top, r.Width - w, r.Height);
    }
    protected override void OnContentClick(DataGridViewCellEventArgs e)
    {
        base.OnContentClick(e);
        var g = this.DataGridView;
        var c = (DataGridViewAllocationControlColumn)this.OwningColumn;
        var r1 = GetContentBounds(e.RowIndex);
        var r2 = g.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, false);
        var p = new Point(r2.Left + r1.Left, r2.Top + r1.Bottom);
        if (c.ContextMenuStrip != null)
            c.ContextMenuStrip.Show(g, p);
    }
    private int GetLabelWidth()
    {
        var c = (DataGridViewAllocationControlColumn)this.OwningColumn;
        var text = c.LabelText;
        return TextRenderer.MeasureText(text, c.DefaultCellStyle.Font).Width;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...