チェックボックス付き行ヘッダーのイベント
投稿者 shu  (社会人)
投稿日時
2017/10/26 13:17:38
Row Headerセルのクリックを検知したいのなら
でどうでしょう?
Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick
Dim dgv = DirectCast(sender, DataGridView)
If e.ColumnIndex = -1 Then
MessageBox.Show($"{e.RowIndex}行目の Header Cell Click")
End If
End Sub
でどうでしょう?
投稿者 あくあ  (社会人)
投稿日時
2017/10/26 21:07:35
shuさん、回答ありがとうございます。
すみません、質問の内容が分かりにくかったですよね。
端的に書くと、RowHeaderCellでイベントを発生させて、Formで受け取るということがしたかったです。
で、出来なかったことは、行のように自動的に増えた分のRowHeaderCellのイベントを処理すればいいのかということでした。
以下の方法で、解決しましたのでコード(といっても、流れがわかる程度の実際には動かないものですけど。もうお分かりかと思いますが、文書で説明するのが下手なので)を載せておきます。
すみません、質問の内容が分かりにくかったですよね。
端的に書くと、RowHeaderCellでイベントを発生させて、Formで受け取るということがしたかったです。
で、出来なかったことは、行のように自動的に増えた分のRowHeaderCellのイベントを処理すればいいのかということでした。
以下の方法で、解決しましたのでコード(といっても、流れがわかる程度の実際には動かないものですけど。もうお分かりかと思いますが、文書で説明するのが下手なので)を載せておきます。
Public Class CustomRowHeader
Inherits DataGridViewRowHeaderCell
Protected Overrides Sub OnClick(e As DataGridViewCellEventArgs)
Me.DataGridView.OnRowHeaderCheckboxChanged()
End Sub
End Class
Public Class CustomDatagridView
Inherits DataGridView
Public Event RowHeaderCheckboxChanged()
Friend Sub OnRowHeaderCheckboxChanged()
RaiseEvent RowHeaderCheckboxChanged()
End Sub
End Class
投稿者 (削除されました)  ()
投稿日時
2017/10/26 23:56:46
(削除されました)
投稿者 (削除されました)  ()
投稿日時
2017/10/27 00:01:47
(削除されました)
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/10/27 11:13:41
CustomDataGridView ではなく
CustomDatagridView になっている点が気になりますが、それはさておき。
> 以下の方法で、解決しましたので
そのコードだとエラーになりませんか?
> Me.DataGridView.OnRowHeaderCheckboxChanged()
上記を下記のようにすれば、一応コンパイルが通るようにはなりましたが。
まぁ、RaiseEvent の後に全角スペースが入っていたり、
RowHeaderCheckboxChanged の後の括弧が全角括弧になっていたので、
実際のコードとは異なっているが故のことではあるのでしょうけれども。
とはいえ現状の実装だと、どの行がクリックされたのかと言う情報が
失われてしまっている点が気がかりです。
イベントの発火タイミングを DataGridViewRowHeaderCell.OnClick にするにしても、
DataGridView.OnCellClick にするにしても、イベントを利用するフォーム側で、
どの行をクリックされたのかを特定できるようにするため、
> Public Event RowHeaderCheckboxChanged()
> Friend Sub OnRowHeaderCheckboxChanged()
> RaiseEvent RowHeaderCheckboxChanged()
> End Sub
の部分は下記のようにした方が、利用者にとっては使いやすいイベントになるかと。
上記を CustomRowHeader 側から呼び出すのであればこんな感じ。
それと、CustomRowHeader 側ですが、
> Protected Overrides Sub OnClick(e As DataGridViewCellEventArgs)
> Me.DataGridView.OnRowHeaderCheckboxChanged()
> End Sub
OnClick をオーバーライドした際に、
元の MyBase.OnClick を呼び忘れているように見えます。
このままだと「CustomRowHeader を継承したクラス」において
Click イベントが発生しないという事態を引き起こしてしまいます。
それとも、あえて意図的に握りつぶしているのでしょうか?
メソッドをオーバーライドするのでれば、基底クラスのメソッドも
呼び出すようにするべきだと思いますし、もし、そもそも
CustomRowHeader をこれ以上継承する予定がないのであれば、
Public NotInheritable Class にしてしまった方が良いでしょう。
この点は、CustomDatagridViewでも同じです。
今後の継承までを考えた設計にしていないなら、
NotInheritable にしておいた方が問題が少ないかと。
逆に、NotInheritable を付与しないのであれば、
さらなる継承が行われることを考慮し、
> Friend Sub OnRowHeaderCheckboxChanged()
の部分を Protected メソッドにしておいた方が良いのでは無いでしょうか。
※Overridable にするかどうかは設計次第
CustomDatagridView になっている点が気になりますが、それはさておき。
> 以下の方法で、解決しましたので
そのコードだとエラーになりませんか?
> Me.DataGridView.OnRowHeaderCheckboxChanged()
上記を下記のようにすれば、一応コンパイルが通るようにはなりましたが。
DirectCast(Me.DataGridView, CustomDatagridView).OnRowHeaderCheckboxChanged()
まぁ、RaiseEvent の後に全角スペースが入っていたり、
RowHeaderCheckboxChanged の後の括弧が全角括弧になっていたので、
実際のコードとは異なっているが故のことではあるのでしょうけれども。
とはいえ現状の実装だと、どの行がクリックされたのかと言う情報が
失われてしまっている点が気がかりです。
イベントの発火タイミングを DataGridViewRowHeaderCell.OnClick にするにしても、
DataGridView.OnCellClick にするにしても、イベントを利用するフォーム側で、
どの行をクリックされたのかを特定できるようにするため、
> Public Event RowHeaderCheckboxChanged()
> Friend Sub OnRowHeaderCheckboxChanged()
> RaiseEvent RowHeaderCheckboxChanged()
> End Sub
の部分は下記のようにした方が、利用者にとっては使いやすいイベントになるかと。
Public Event RowHeaderCheckboxChanged As DataGridViewRowEventHandler
Friend Sub OnRowHeaderCheckboxChanged(e As DataGridViewRowEventArgs)
RaiseEvent RowHeaderCheckboxChanged(Me, e)
End Sub
上記を CustomRowHeader 側から呼び出すのであればこんな感じ。
Dim dgv = TryCast(Me.DataGridView, CustomDatagridView)
If dgv IsNot Nothing Then
dgv.OnRowHeaderCheckboxChanged(New DataGridViewRowEventArgs(Me.OwningRow))
End If
それと、CustomRowHeader 側ですが、
> Protected Overrides Sub OnClick(e As DataGridViewCellEventArgs)
> Me.DataGridView.OnRowHeaderCheckboxChanged()
> End Sub
OnClick をオーバーライドした際に、
元の MyBase.OnClick を呼び忘れているように見えます。
このままだと「CustomRowHeader を継承したクラス」において
Click イベントが発生しないという事態を引き起こしてしまいます。
それとも、あえて意図的に握りつぶしているのでしょうか?
メソッドをオーバーライドするのでれば、基底クラスのメソッドも
呼び出すようにするべきだと思いますし、もし、そもそも
CustomRowHeader をこれ以上継承する予定がないのであれば、
Public NotInheritable Class にしてしまった方が良いでしょう。
この点は、CustomDatagridViewでも同じです。
今後の継承までを考えた設計にしていないなら、
NotInheritable にしておいた方が問題が少ないかと。
逆に、NotInheritable を付与しないのであれば、
さらなる継承が行われることを考慮し、
> Friend Sub OnRowHeaderCheckboxChanged()
の部分を Protected メソッドにしておいた方が良いのでは無いでしょうか。
Protected Friend Overridable Sub OnRowHeaderCheckboxChanged(e As DataGridViewRowEventArgs)
※Overridable にするかどうかは設計次第
投稿者 あくあ  (社会人)
投稿日時
2017/10/27 23:16:11
魔界の仮面弁士さん、いつもありがとうございます。
>CustomDataGridView ではなく
>CustomDatagridView になっている点が気になりますが、それはさておき。
気づきませんでした。
>そのコードだとエラーになりませんか?
はい。括弧内に書いた通り、動かないコードです。
CustomRowHeaderのOnClickを発火点に、CustomDatagridViewのプロシジャーを呼び出して、CustomDatagridViewからイベントを発行(っていう言い方でいいんですかね)してるという考え方がわかってもらえればいいかなと、思って書きました。
なので、いろいろ端折ってます。(EventArgsの部分とか、Castとか)
これだと、不親切でしたね。反省します。
>OnClick をオーバーライドした際に、
>元の MyBase.OnClick を呼び忘れているように見えます。
これは、忘れてました。
ご指摘ありがとうございます。
あと、CustomRowHeader、CustomDatagridViewをさらに継承するかという点ですが、さらに継承するなんて思いもつかなかったです。
とりあえず、今回は継承に耐えられるコードかの検証が出来てないので、NotInheritableを付けて継承不可にしました。
今回は、いろいろ勉強させて頂いて、楽しかったです。
改めて、shuさん、魔界の仮面弁士さん、ありがとうございました。
>CustomDataGridView ではなく
>CustomDatagridView になっている点が気になりますが、それはさておき。
気づきませんでした。
>そのコードだとエラーになりませんか?
はい。括弧内に書いた通り、動かないコードです。
CustomRowHeaderのOnClickを発火点に、CustomDatagridViewのプロシジャーを呼び出して、CustomDatagridViewからイベントを発行(っていう言い方でいいんですかね)してるという考え方がわかってもらえればいいかなと、思って書きました。
なので、いろいろ端折ってます。(EventArgsの部分とか、Castとか)
これだと、不親切でしたね。反省します。
>OnClick をオーバーライドした際に、
>元の MyBase.OnClick を呼び忘れているように見えます。
これは、忘れてました。
ご指摘ありがとうございます。
あと、CustomRowHeader、CustomDatagridViewをさらに継承するかという点ですが、さらに継承するなんて思いもつかなかったです。
とりあえず、今回は継承に耐えられるコードかの検証が出来てないので、NotInheritableを付けて継承不可にしました。
今回は、いろいろ勉強させて頂いて、楽しかったです。
改めて、shuさん、魔界の仮面弁士さん、ありがとうございました。
Datagridviewのチェックボックス付きのヘッダーセルを作りました。
DatagridviewのRowTemplateのHeaderCellにこのチェックボックス付きヘッダーセルを設定して、表示することまではできました。
この後、チェックボックスの状態が変わったときに発生するイベント(CheckedChanged)を作ろとして詰まってしまいました。RaiseEventでイベントを発生させて、Form側で受け取ればいいのかと思いましたが、行が追加されるとイベントが取得できなくなってしまいます。これは何となく、Handlesの後ろに新規行が書かれてないせいだと思っています。
今考えているのが、カスタムDatagridviewを用意し、その中にチェックボックス付きのヘッダーセルからのイベントを受ける用のプロシジャーを用意し、このプロシジャーで再度、RaiseEventさればいいのかと思っています。
そこで、お聞きしたいのが、イベントを受ける用のプロシジャーにDatagridviewの行数分だけ、チェックボックス付きヘッダーセルが登録されることになると思いますが(すみません、この辺どういう表現をすればいいのかわからないので、わからなかったら質問してください)、多量に登録していいものなのでしょうか?
また、もっと簡単にできる方法があるのでしょうか?HeaderCellにRaiseCellClick等あるので、どうしてもダメなら、これを使おうかと思っています。
現在、自宅なので上記のコードをのせることが出来ないのですが、後ほど結果は上げさせていただきます。