2

Популярный способ (1, 2) для пользовательской окраски предметов в DataGridViewComboBox - это обработка события DataGridView1. EditingControlShowing и наладка DrawItem обработчики событий там:Как сделать пользовательский DataGridViewComboBox зависимым только от его DataGridViewComboBoxColumn?

private void dataGridView1_EditingControlShowing(
    object sender, 
    DataGridViewEditingControlShowingEventArgs e) 
{ 
    theBoxCell = (ComboBox) e.Control; 
    theBoxCell.DrawItem += theBoxCell_DrawItem; 
    theBoxCell.DrawMode = DrawMode.OwnerDrawVariable; 
} 

Вы видите, что это не так: она использует событие контроля уровня осуществлять работу по столбцам. Но что, если у меня есть 50+ datagridviews? Покраска пользовательских комбинированных ящиков должна обрабатываться за экземпляр колонки, оставив контрольный уровень неповрежденным.

Минимальная реализация обработки столбцов ниже. Единственная проблема, с которой я столкнулся, заключается в том, что метод OnDrawItem() не вызван. Что мне не хватает? (Вы можете видеть, что фуксии фона переопределение от того же класса работает.)

(Чтобы воспроизвести, просто вставьте следующий код в файл класса и добавить столбец типа DataGridViewCustomPaintComboBoxColumn к вашим dataGridView1.)

public class DataGridViewCustomPaintComboBoxColumn : DataGridViewComboBoxColumn 
{ 
    public DataGridViewCustomPaintComboBoxColumn() 
    { 
     base.New(); 
     CellTemplate = new DataGridViewCustomPaintComboBoxCell(); 
    } 

} 

public class DataGridViewCustomPaintComboBoxCell : DataGridViewComboBoxCell 
{ 
    public override Type EditType { 
     get { return typeof(DataGridViewCustomPaintComboBoxEditingControl); } 
    } 

    protected override void Paint(...) 
    { 
     //painting stuff for incative cells here - works well 
    } 

} 

public class DataGridViewCustomPaintComboBoxEditingControl : DataGridViewComboBoxEditingControl 
{ 
    public override Color BackColor { // property override only for testing 
     get { return Color.Fuchsia; } // test value works as expected 
     set { base.BackColor = value; } 
    } 

    protected override void OnPaint(PaintEventArgs e) // never called - why? 
    { 
     base.OnPaint(e) 
    } 

    protected override void OnDrawItem(DrawItemEventArgs e) // never called - why? 
    { 
     base.OnDrawItem(e) 
    } 
} 

ответ

3

Единственная проблема у меня есть то, что метод OnDrawItem() не вызывался. Что мне не хватает?

То, что вы видите внутри сфокусированного DataGridViewComboBoxCell в значительной степени «реальным» ComboBox и вам нужна ссылка на него, чтобы вклиниться в его DrawItem событие! (Вы можете посмотреть коллекцию Controls в DGV, чтобы увидеть, что есть еще один, когда ComboBoxCell имеет фокус .. DataGridViewComboBoxEditingControl непосредственно произошли от ComboBox)

Примечание: Одно из отличий к из коробки CombBox есть то, что по умолчанию установлено DrawMode = OwnerDrawVariable. Если вы хотите заменить его тем, что вы создаете сами, не забудьте установить его в код!

Похоже, это то, чего вам не хватает!

Если вы можете создать свой собственный DataGridViewComboBoxEditingControl и заставить его отображаться в вашем DGV, вы все настроены.


Альтернативная модель, которую я часто использую это своего рода «декоратор», который реализует пользовательский рисунок для всех столбцов, регистрирующих с ним.

DgvCombBoxPainter.Register(DataGridView dgv, stringOrInt columnNameOrIndex..) 

В функции регистрации было бы зацепить в необходимых методов DGV, то есть EditingControlShowing получить на ComboBox вы видите, когда DGV имеет фокус и CellPainting для других случаев.

Декоратор может быть статичным и нуждается только в одном ComboBox для всех зарегистрированных вами столбцов, так как только один может иметь фокус за раз.

Если вы можете обработать весь код окраски в декораторе, тем лучше. Из событий, он всегда может достигнуть назад к DataGridView через sender и свойства клеток передаются через параметр DataGridViewCellPaintingEventArgs ..

Вы даже можете поставить ссылку на текущую ячейку в ComboBox ссылки-х Tag:

theBoxCell.Tag = dataGridView1.CurrentCell; 

Если вы хотите, вы также можете предоставить отдельным делегатам возможность вызывать событие (ы) рисования при регистрации. Вы должны были бы сохранить список этих, может быть, в словаре.

+0

Я понимаю вашу идею статического декоратора, но прежде чем принять ответ, я не уверен в ваших рассуждениях. Как вы говорите, «DataGridViewComboBoxCell» не является элементом управления. Он используется для рисования реплик элемента управления в неактивных ячейках (и служит одному экземпляру управления для редактируемой ячейки). Таким образом, переопределение своего события 'OnPaint()' работает, как ожидалось (я расширил указанный выше источник). OTOH 'DataGridViewComboBoxEditingControl' * - это элемент управления (прямой потомок' ComboBox'), поэтому, когда его экземпляр создан для использования с событием 'EditingControlShowing', его переопределенные' OnPaint() 'и' ItemDraw() 'должны работать, нет? – miroxlav

+0

Да, я думаю, вы все поняли, за исключением того, что я не уверен, что события Paint/OnPaint вступят в силу или даже начнут стрелять; они заменяются событием DrawItem/OnDrawItem. Чтобы нарисовать часть, которая не выпала, вам нужно проверить «e.Index == -1». – TaW

+0

На данный момент я не уверен, правильно ли мы думаем. Мне нужно подтвердить. Мои пункты: Во-первых: [источник ссылки для DataGridViewComboBoxEditingControl.cs] (http://bit.ly/1Ojc1Zl) делает * не * показывает какие-либо манипуляции с его предшественником ComboBox. (Без отключения материала рисования и т. Д.). Второе: переопределение 'OnPaint()' и 'OnDrawItem()' does * not * работают даже со стандартным простым 'ComboBox'. Поэтому, возможно, после того, как вы узнаете, как правильно создавать выпадающие на заказ выпадающие списки, никакой декоратор не может потребоваться - просто правильно написанный потомок 'DataGridViewComboBoxEditingControl' :). Позвольте мне проверить, что ... – miroxlav

Смежные вопросы