Мой Kbyte.Ru
Рассылка Kbyte.Ru
Группы на Kbyte.Ru
Партнеры Kbyte.Ru
Реклама
Сделано руками
Сделано руками
> Статьи - Николай (Neco) Увалиев -

Visual Basic .NET - Разработка элементов управления

Все статьи / Интерфейс / Элементы управления Windows / Разработка элементов управления

Наследование в Visual Basic .Net

Автор: Николай (Neco) Увалиев | добавлено: 03.03.2010, 16:20 | просмотров: 4083 (0+) | комментариев: 0 | рейтинг: *x3

Если кто-нибудь уже сталкивался с мелкомягким контролом DataGridView, то наверняка порадовался обилию возможностей, которые он предлагает. Однако, когда дело доходит до реального кодинга, начинаешь хотеть чего-то большего. Мне, к примеру, понадобилось, чтобы внутри таблицы был ComboBox – конечно, он там есть, но мне понадобилось, чтобы в нём можно было ЛИБО печатать, ЛИБО выбирать. Т.е., если в списке не оказалось нужной нам вещицы, то мы могли впечатать её и тем самым дополнить список.

Думал, что придётся извращаться. Однако, добры молодцы из нашей любимой компании уже предусмотрели ходы для развития своего контрола в таких направлениях, поэтому у меня всё получилось и сейчас я попробую повторить.

Кстати, всё это практически один в один перерисовано с MSDN – но т.к. я и сам в своё время не был счастливым обладателем оной, то допускаю, что и сейчас не все имеют свободный доступ к этому ресурсу и поэтому статья имеет место быть.

 

Для начала создайте что-нибудь подобное моему произведению искусства (хотя вряд ли у вас так получиться). Я назвал грид – dgvTest, а кнопку btnFill.

 

 

Если создали, то можно считать, что самая сложная часть позади. Всё остальное - семечки.

Попробуем добавить столбец в нашу таблицу и посмотрим, что нам предложат:

 

 

Можете выбрать этот пункт и поэкспериментировать с ним. В результате, вы увидите, что того, чего я от него хочу, он не может (если увидите обратное, дайте мне знать). Для того, чтобы в этом списке появилось-таки то, что нам нужно, нам потребуется создать три (!!! ну хорошо, что не четыре) новых класса. Их можно наследовать и от чистого DataGridViewCell, но т.к. мне достаточно простого отображения текста в режиме просмотра, то я буду наследовать свой ключевой класс от DataGridViewTextBoxCell.

В чём основная фишка: когда вы начинаете редактировать какое-либо поле, вы редактируете EditingControl данного грида. EditingControl позволяет редактировать вам значение в том виде, в котором его удобно редактировать, и сообщает своей ячейке (которую вы меняете) форматированное значение, которое удобно просматривать.

Однако, всё касается ячеек, а нам надо применить такую схему ко всем ячейкам, определённой колонки (ну чтобы выбрать её из списка на визуальном этапе). Нет проблем - создаём новый класс, наследующий DataGridViewColumn:

 

Public Class clsNecoColumn
 Inherits DataGridViewColumn
End Class

 

После выполнения команды Build проекта, наш список колонок измениться следующим образом:

 

 

Создадим, пару таких колонок и пару обычных текстовых, чтобы всё это дело протестировать. Нажмём океюшки и увидим:

 

 

Бамс! Нам что-то втирают на непонятном буржуйском. Пошарившись по словарям, выясняем, что речь идёт о некоем «ячеистом шаблоне».

Тогда создадим класс-ячейку, которая будет браться за шаблон при работе с данной колонкой:

 

Public Class clsNecoCell

 Inherits DataGridViewTextBoxCell

End Class

 

И дополним, наш класс-колонку кодом, чтобы получилось:

 

Public Class clsNecoColumn

  Public Class clsNecoColumn

  Inherits DataGridViewColumn

  Public Sub New()

  MyBase.New(New clsNecoCell)

  End Sub

  Public Overrides Property CellTemplate() As System.Windows.Forms.DataGridViewCell

  Get

  Return MyBase.CellTemplate

  End Get

  Set(ByVal value As System.Windows.Forms.DataGridViewCell)

  MyBase.CellTemplate = value

  End Set

  End Property

  End Class

End Class

 

Перестроим проект и попробуем ещё раз создать колонки. Не знаю как, но у меня получилось:

 

 

Добавим в событие кнопки немного хлама:

 

 Private Sub btnFill_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFill.Click

 dgvTest.RowCount = 10

 End Sub

 

Запустим проект и увидим… н-да, что пока ещё нечего праздновать, т.к. все наши поля ведут себя абсолютно одинаково как при просмотре, так и при редактировании. Ну просмотр нас всегда устраивал, поэтому переключимся на редактирование. У нашего класса clsNecoCell есть свойство EditType недвусмысленно намекающее на его предназначение. Нам надо, чтобы в момент редактирования он становился КомбоБоксом, поэтому дополним наш класс ячейки до следующего вида:

 

 

Public Class clsNecoCell

 Inherits DataGridViewTextBoxCell

 Public Overrides ReadOnly Property EditType() As System.Type

 Get

 Return GetType(ComboBox)

 End Get

 End Property

End Class

 

Запустим, проект, кликнем два раза по полю, которое мы хотим редактировать через комбо и…:

 

 

Бамс! Нам опять что-то втирают про то, что мы не умеем программировать. Останавливаем слюни, разбираемся и выясняем, что наш класс ComboBox, тип которого мы возвращали в свойстве EditType, не поддерживает интерфейс IDataGridViewEditingControl. Что ж, придётся писать ещё один класс, который будет работать как комбо и при этом поддерживать этот интерфейс:

 

Public Class clsNecoControl

 Inherits ComboBox

 Implements IDataGridViewEditingControl

End Class

 

Когда вы введёте Implements IDataGridViewEditingControl, ваш класс автоматически дополниться кучей функций и свойств, которые он должен поддерживать вследствие следования формату интерфейса. Их довольно много, поэтому я сразу приведу класс к тому виду, в котором он должен стать в конце:

 

Public Class clsNecoControl

 Inherits ComboBox

 Implements IDataGridViewEditingControl

 

 Dim m_DataCtl As DataGridView ' храним здесь родительский грид

 Dim m_row As Integer  ' храним здесь индекс редактируемого элемента

 Dim m_changed As Boolean  ' менялись или нет

 

 ' Чтобы наш контрол не светился на гриде, как голый зад при луне, надо привести его к стилю

 ' нашего грида

 Public Sub ApplyCellStyleToEditingControl(ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle) Implements System.Windows.Forms.IDataGridViewEditingControl.ApplyCellStyleToEditingControl

 With dataGridViewCellStyle

 Me.Font = .Font

 Me.ForeColor = .ForeColor

 Me.BackColor = .BackColor

 End With

 End Sub

 

 ' Свойство для связи с родительским DataGridView

 Public Property EditingControlDataGridView() As System.Windows.Forms.DataGridView Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlDataGridView

 Get

 Return m_DataCtl

 End Get

 Set(ByVal value As System.Windows.Forms.DataGridView)

 m_DataCtl = value

 End Set

 End Property

 

 Public Property EditingControlFormattedValue() As Object Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlFormattedValue

 Get

 Return Me.Text

 End Get

 Set(ByVal value As Object)

 Me.Text = CStr(value)

 End Set

 End Property

 

 ' В этом виде текст будет возвращён в таблицу

 Public Function GetEditingControlFormattedValue(ByVal context As System.Windows.Forms.DataGridViewDataErrorContexts) As Object Implements System.Windows.Forms.IDataGridViewEditingControl.GetEditingControlFormattedValue

 Return Me.Text

 End Function

 

 Public Property EditingControlRowIndex() As Integer Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlRowIndex

 Get

 Return m_row

 End Get

 Set(ByVal value As Integer)

 m_row = value

 End Set

 End Property

 

 Public Property EditingControlValueChanged() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlValueChanged

 Get

 Return m_changed

 End Get

 Set(ByVal value As Boolean)

 m_changed = value

 End Set

 End Property

 

 Public Function EditingControlWantsInputKey(ByVal keyData As System.Windows.Forms.Keys, ByVal dataGridViewWantsInputKey As Boolean) As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.EditingControlWantsInputKey

 ' ну и пусть себе хочет

 End Function

 

 Public ReadOnly Property EditingPanelCursor() As System.Windows.Forms.Cursor Implements System.Windows.Forms.IDataGridViewEditingControl.EditingPanelCursor

 Get

 Return Cursors.Cross

 End Get

 End Property

 

 Public Sub PrepareEditingControlForEdit(ByVal selectAll As Boolean) Implements System.Windows.Forms.IDataGridViewEditingControl.PrepareEditingControlForEdit

 ' готовимся морально

 End Sub

 

 Public ReadOnly Property RepositionEditingControlOnValueChange() As Boolean Implements System.Windows.Forms.IDataGridViewEditingControl.RepositionEditingControlOnValueChange

 Get

 Return False

 End Get

 End Property

 

 ' Процедура, которая необязательна для соответствия интерфейсу, но

 ' без которой наш грид не будет реагировать на изменения

 Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)

 m_changed = True

 Me.EditingControlDataGridView.NotifyCurrentCellDirty(True)

 MyBase.OnTextChanged(e)

 End Sub

End Class

 

Теперь вся наша музыка должна начать играть за тем исключением, что наш комбо всегда будет появляться с тем текстом, который в него ввели последний раз (т.к. это всё тот же экземпляр класса). Можно, конечно, выдать это за фичу, но лучше дополнить класс ячейки до следующего вида:

 

Public Class clsNecoCell

 Inherits DataGridViewTextBoxCell

 

 Public Overrides ReadOnly Property EditType() As System.Type

 Get

 Return GetType(clsNecoControl)

 End Get

 End Property

 Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, ByVal initialFormattedValue As Object, ByVal dataGridViewCellStyle As System.Windows.Forms.DataGridViewCellStyle)

 MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)

 Dim tmp As clsNecoControl = CType(Me.DataGridView.EditingControl, clsNecoControl)

 tmp.Text = CStr(Me.Value)

 End Sub

End Class

 

Напоследок дополним класс-комбо первоначальным смыслом:

 

 Public Sub New()

 Me.AutoCompleteMode = Windows.Forms.AutoCompleteMode.Suggest

 Me.AutoCompleteSource = Windows.Forms.AutoCompleteSource.ListItems

 Me.Items.Add("Иванов")

 Me.Items.Add("Петров")

 Me.Items.Add("Сидоров")

 Me.Items.Add("Мздряев")

 Me.Sorted = True

 End Sub

 

 Protected Overrides Sub OnValidated(ByVal e As System.EventArgs)

 If Me.SelectedIndex = -1 Then

 Me.Items.Add(Me.Text)

 End If

 MyBase.OnValidated(e)

 End Sub

 

И окончательно протестируем проект:

 

 

Ну вроде пришли к тому, с чего начали…

+ Добавить в избранное
    ? Помощь
Об авторе

Николай (Neco) Увалиев

Нет информации об авторе...

См. также:
Профиль автора
Николай (Neco) Увалиев
Последние комментарии (всего: 0)

Добавлять комментарии могут только зарегистрированные пользователи сайта.
Если у Вас уже есть учетная запись на Kbyte.Ru, пройдите процедуру авторизации OpenID.
Если Вы еще не зарегистрированы на Kbyte.Ru - зарегистрируйтесь.


Нет комментариев...

Авторизация
 
OpenID
Зарегистрируйся и получи 10% скидку на добавление своего сайта в каталоги! Подробнее »
Поиск по сайту
Люди на Kbyte.Ru
Реклама
Счетчики