チェックボックス付き行ヘッダーのイベント への返答

投稿で使用できる特殊コードの説明。(別タブで開きます。)
本名は入力しないようにしましょう。
投稿した後で削除するときに使うパスワードです。返答があった後は削除できません。
返答する人が目安にします。相手が小学生か社会人かで返答の仕方も変わります。
最初の投稿が質問の場合、質問者が解決時にチェックしてください。(以降も追加書き込み・返信は可能です。)
※「過去ログ」について書くときはその過去ログのURLも書いてください。

以下の返答は逆順(新しい順)に並んでいます。

投稿者 あくあ  (社会人) 投稿日時 2017/10/27 23:16:11
魔界の仮面弁士さん、いつもありがとうございます。

>CustomDataGridView ではなく
>CustomDatagridView になっている点が気になりますが、それはさておき。

気づきませんでした。

>そのコードだとエラーになりませんか?
はい。括弧内に書いた通り、動かないコードです。
CustomRowHeaderのOnClickを発火点に、CustomDatagridViewのプロシジャーを呼び出して、CustomDatagridViewからイベントを発行(っていう言い方でいいんですかね)してるという考え方がわかってもらえればいいかなと、思って書きました。
なので、いろいろ端折ってます。(EventArgsの部分とか、Castとか)

これだと、不親切でしたね。反省します。


>OnClick をオーバーライドした際に、
>元の MyBase.OnClick を呼び忘れているように見えます。
これは、忘れてました。
ご指摘ありがとうございます。


あと、CustomRowHeader、CustomDatagridViewをさらに継承するかという点ですが、さらに継承するなんて思いもつかなかったです。
とりあえず、今回は継承に耐えられるコードかの検証が出来てないので、NotInheritableを付けて継承不可にしました。


今回は、いろいろ勉強させて頂いて、楽しかったです。
改めて、shuさん、魔界の仮面弁士さん、ありがとうございました。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/10/27 11:13:41
CustomDataGridView ではなく
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 00:01:47
(削除されました)
投稿者 (削除されました)  () 投稿日時 2017/10/26 23:56:46
(削除されました)
投稿者 あくあ  (社会人) 投稿日時 2017/10/26 21:07:35
shuさん、回答ありがとうございます。

すみません、質問の内容が分かりにくかったですよね。
端的に書くと、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
投稿者 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/25 23:54:27
お世話になっております。

Datagridviewのチェックボックス付きのヘッダーセルを作りました。
DatagridviewのRowTemplateのHeaderCellにこのチェックボックス付きヘッダーセルを設定して、表示することまではできました。

この後、チェックボックスの状態が変わったときに発生するイベント(CheckedChanged)を作ろとして詰まってしまいました。RaiseEventでイベントを発生させて、Form側で受け取ればいいのかと思いましたが、行が追加されるとイベントが取得できなくなってしまいます。これは何となく、Handlesの後ろに新規行が書かれてないせいだと思っています。

今考えているのが、カスタムDatagridviewを用意し、その中にチェックボックス付きのヘッダーセルからのイベントを受ける用のプロシジャーを用意し、このプロシジャーで再度、RaiseEventさればいいのかと思っています。

そこで、お聞きしたいのが、イベントを受ける用のプロシジャーにDatagridviewの行数分だけ、チェックボックス付きヘッダーセルが登録されることになると思いますが(すみません、この辺どういう表現をすればいいのかわからないので、わからなかったら質問してください)、多量に登録していいものなのでしょうか?
また、もっと簡単にできる方法があるのでしょうか?HeaderCellにRaiseCellClick等あるので、どうしてもダメなら、これを使おうかと思っています。

現在、自宅なので上記のコードをのせることが出来ないのですが、後ほど結果は上げさせていただきます。