- PR -

派生クラスのイベントを基底クラスでハンドリングする方法

1
投稿者投稿内容
まよかん
常連さん
会議室デビュー日: 2003/08/10
投稿数: 27
お住まい・勤務地: 大阪
投稿日時: 2006-10-13 07:58
C#でWindowsアプリケーションを開発しています。

派生クラスで発生したイベントを基底クラスでハンドリングする方法ってありますでしょうか。
何がやりたいかというと、「〜ボタンが押された」や「〜が選択された」などをログに残していきたいんですが、全てのイベントでその処理を書くのはイヤなんです。

ボタンコントロールを継承すれば可能なのは理解しておりますが、そうなるとコンボボックスも、チェックボックスも・・・と多数のコントロールを継承して用意しなければなりません。

全てのボタンクリック時に発生するイベントとかがあればうれしいんですが、そんな都合のいいものはないですかね。

みなさんは、こういった派生クラスのイベントをハンドリングしたいといった場合、どのような実装をされますでしょうか?
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2006-10-13 08:42
引用:

まよかんさんの書き込み (2006-10-13 07:58) より:
派生クラスで発生したイベントを基底クラスでハンドリングする方法ってありますでしょうか。


無い。考えても見てほしい。基底クラスが派生クラスの実装を知っているはず無いじゃないか。

引用:

ボタンコントロールを継承すれば可能なのは理解しておりますが、そうなるとコンボボックスも、チェックボックスも・・・と多数のコントロールを継承して用意しなければなりません。


???
先の質問はどういう方法で実現するつもりだったの?既存のコントロールの基底クラスを変更するなんて出来るはずが無いですし・・・。

引用:

全てのボタンクリック時に発生するイベントとかがあればうれしいんですが、そんな都合のいいものはないですかね。


割と簡単に出来ますよ。Form.Controlsコレクションを使って、Formに関連付けられている全てのButtonクラスのClickイベントに共通のハンドラを登録すればよいんです。
R・田中一郎
ぬし
会議室デビュー日: 2005/11/03
投稿数: 979
投稿日時: 2006-10-13 08:50
引用:

甕星さんの書き込み (2006-10-13 08:42) より:

引用:

ボタンコントロールを継承すれば可能なのは理解しておりますが、そうなるとコンボボックスも、チェックボックスも・・・と多数のコントロールを継承して用意しなければなりません。


???
先の質問はどういう方法で実現するつもりだったの?既存のコントロールの基底クラスを変更するなんて出来るはずが無いですし・・・。


ご自身で作られたフォームクラスを派生させているんでしょうかね?
僕は、似たようなデザインのフォームを作る場合などに時々やりますが。

引用:

まよかんさんの書き込み (2006-10-13 07:58) より:

派生クラスで発生したイベントを基底クラスでハンドリングする方法ってありますでしょうか。
何がやりたいかというと、「〜ボタンが押された」や「〜が選択された」などをログに残していきたいんですが、全てのイベントでその処理を書くのはイヤなんです。



ログ記録機能つきボタンコントロールを自作して、これをフォームにベタベタ貼り付ければ良いのでは?

_________________
R・田中一郎 @ わんくま同盟  -  R.Tanaka.Ichiro’s Blog ← ブログはじめました

[ メッセージ編集済み 編集者: R・田中一郎 編集日時 2006-10-13 10:14 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-10-13 09:01
引用:

R・田中一郎さんの書き込み (2006-10-13 08:50) より:

ログ記録機能つきボタンコントロールを自作して、これをフォームにベタベタ貼り付ければ良いのでは?


私は、それ 'も' イヤですね。
この場合、動的にイベント ハンドラをログ用に設定し直した方が変更に強いです。

その前に、ロギング ツールで十分だと思っておりますが。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Ahf
大ベテラン
会議室デビュー日: 2006/08/16
投稿数: 172
投稿日時: 2006-10-13 09:27
利用したい状況にもよるのですが、Form上に存在するコントロールのイベントを
後付けで察知したいというだけでしたら、できそうな感じです。

AddHandlerを利用してイベントの2重登録のような状態にしてしまうことで
対応できるかもしれません。

コード:
Private Sub frmTemplate_Load(
  ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    AddHandler TextBox1.Click, AddressOf testClick
End Sub

Private Sub testClick(ByVal sender As Object, ByVal e As System.EventArgs)
  Console.WriteLine("TestClick")
End Sub

Private Sub TextBox1_Click(
    ByVal sender As Object, 
    ByVal e As System.EventArgs) Handles TextBox1.Click
        Console.WriteLine("TextBox_Click")
End Sub



実行結果としては、
TextBox_Click
TestClick
といった感じで出力されたのを確認しています・・・。

ただ本当にこんな使い方をしてよいかどうかは怪しいんですけどね。

#まだClickイベント程度でしか試していませんので全てで利用できるかは不明です
よこけん
大ベテラン
会議室デビュー日: 2006/01/31
投稿数: 216
投稿日時: 2006-10-13 11:56
一つのイベントに複数のイベントハンドラを登録した場合、それらの実行順序って保障されてなかったような・・・。
Ahf
大ベテラン
会議室デビュー日: 2006/08/16
投稿数: 172
投稿日時: 2006-10-13 12:09
引用:

よこけんさんの書き込み(2006-10-13 11:56)より
一つのイベントに複数のイベントハンドラを登録した場合、それらの実行順序って保障されてなかったような・・・。



はい、私もそのように記憶してます。
そのため「ログを取る」程度に限定されてしまうと思います。

今回は使えるかな・・・?ということで・・・。
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2006-10-13 18:19
拡張プロバイダを実装すれば、他のコントロールのイベントをロギングするコンポーネントが作れそうです。

以下、サンプル。
コード:
Imports System.ComponentModel

<ProvideProperty("Logging", GetType(Control))> _
Public Class ControlEventWatcher
    Inherits Component
    Implements IExtenderProvider

    Private LoggingPropertyValues As Generic.Dictionary(Of Control, Boolean) _
        = New Generic.Dictionary(Of Control, Boolean)

    Public Function CanExtend(ByVal extendee As Object) As Boolean _
    Implements System.ComponentModel.IExtenderProvider.CanExtend
        Return (TypeOf extendee Is Control) AndAlso (Not TypeOf extendee Is ControlEventWatcher)
    End Function

    Private Sub Control_Click(ByVal sender As Object, ByVal e As EventArgs)
        Diagnostics.Debug.WriteLine(CType(sender, Control).Name & " Clicked")
    End Sub

    <DefaultValue(GetType(Boolean), "False")> _
    Public Function GetLogging(ByVal ctrl As Control) As Boolean
        Dim ret As Boolean = False

        If Me.LoggingPropertyValues.ContainsKey(ctrl) Then
            ret = Me.LoggingPropertyValues(ctrl)
        Else
            Me.LoggingPropertyValues.Add(ctrl, ret)
        End If

        Return ret
    End Function

    Public Sub SetLogging(ByVal ctrl As Control, ByVal value As Boolean)
        Me.LoggingPropertyValues(ctrl) = value

        If value Then
            AddHandler ctrl.Click, AddressOf Me.Control_Click
        Else
            RemoveHandler ctrl.Click, AddressOf Me.Control_Click
        End If

    End Sub

End Class

1

スキルアップ/キャリアアップ(JOB@IT)