- 題名: BindingListの要素内の値が変更されたらイベントを発生させたい
- 日時: 2013/05/27 12:02:39
- ID: 31589
- この記事の返信元:
- (なし)
- この記事への返信:
- [31591] Re[1]: BindingListの要素内の値が変更されたらイベントを発生させたい2013/05/27 19:43:53
- ツリーを表示
■No31589に返信(やむさんの記事) > listItem.differenceの値を計算して設定させたいのです。 であれば、 '回収残 Public Property difference As Integer = 0 とするのではなく '回収残 Public ReadOnly Property difference As Integer Get Return bill - (deposit + commission) End Get End Property としておいた方が手っ取り早いかと。 > どちらにも対応させる方法はないでしょうか。 そもそも、DataTable/DataSet のまま管理しては駄目なのでしょうか? DataTable そのものを DataGridView にバインドしていれば、 元の DataTable を編集することで、DataGridView の表示は変わりますし、 difference 列の件についても、「式列」を用意するだけで済むはずです。 Public Class Form1 Private WithEvents DataGridView1 As DataGridView Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load DataGridView1 = New DataGridView() DataGridView1.Dock = DockStyle.Fill Me.Controls.Add(DataGridView1) DataGridView1.DataSource = CreateSampleTable() End Sub Private Function CreateSampleTable() As DataTable Dim tbl As New DataTable() '実際はデータベースから取得 tbl.Columns.Add("code") tbl.Columns.Add("name") tbl.Columns.Add("bill", GetType(Decimal)) tbl.Columns.Add("deposit", GetType(Decimal)) tbl.Columns.Add("commission", GetType(Decimal)) tbl.PrimaryKey = {tbl.Columns("code")} 'サンプルデータ Dim r As New Random() For n As Integer = 10 To 50 tbl.Rows.Add(CStr(n * 10 + 1), StrDup(n \ 2, "*"), r.Next(6, 10), r.Next(3, 5), r.Next(0, 3)) Next '本題の「difference」列を作成 tbl.Columns.Add("difference", GetType(Decimal), "bill - (deposit + commission)") Return tbl End Function End Class もしも BindingList で管理した方が都合が良いのあれば、 「変更通知」の機能を実装する必要があります。 http://msdn.microsoft.com/ja-jp/library/xz45s2bh.aspx 具体的には、listItem クラスに INotifyPropertyChanged を Implements した上で、それぞれのプロパティを自動実装プロパティから カスタム実装にして、値が変更されたときに INotifyPropertyChanged の PropertyChanged イベントを発行するようにします。 '請求額 Private _bill As Integer = 0 Public Property bill() As Integer Get Return _bill End Get Set(ByVal value As Integer) _bill = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("bill")) End Set End Property
魔界の仮面弁士様 ありがとうございます。 > そもそも、DataTable/DataSet のまま管理しては駄目なのでしょうか? ダメというわけではないのですが、個人的な好みの問題で わざわざDataSourceに指定するクラスを作成して管理しています。 > もしも BindingList で管理した方が都合が良いのあれば、 > 「変更通知」の機能を実装する必要があります。 > http://msdn.microsoft.com/ja-jp/library/xz45s2bh.aspx 教えていただいた方法で、listItemクラスを変更し、frm側でイベントを拾う 方法を試してみました。 ところが、最初のsetData()時には問題なくイベントを拾ってくれるのですが、 DataGridViewに直接入力した場合にはイベントを拾いません。 何がおかしいのか、アドバイス頂けると幸いです。 宜しくお願いします。 -- 以下ソース 変更したlistItemクラスと、frmクラスの追加部分のみ抜出 Public Class frm Private WithEvents item As listItem '追加 '追加 DataGridViewに直接値を入力した際にここを通らない Private Sub item_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Handles item.PropertyChanged Dim line As listItem = DirectCast(sender, listItem) line.difference = line.bill - (line.deposit + line.commission) End Sub End Class Public Class listItem Implements INotifyPropertyChanged Dim _bill As Integer = 0 Dim _deposit As Integer = 0 Dim _commission As Integer = 0 Public Property code As String = "" Public Property name As String = "" Public Property bill As Integer Get Return _bill End Get Set(value As Integer) If Not value = _bill Then _bill = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("bill")) End If End Set End Property Public Property deposit As Integer Get Return _deposit End Get Set(value As Integer) If Not value = _deposit Then _deposit = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("deposit")) End If End Set End Property Public Property commission As Integer Get Return _commission End Get Set(value As Integer) If Not value = _commission Then _commission = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("commission")) End If End Set End Property Public Property difference As Integer = 0 Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged End Class
自己解決です。 setData()内でitem を new した際、イベントの紐づけを行うのが抜けていました。 大変お騒がせしました。 アドバイス頂いた魔界の仮面弁士様、ありがとうございました 。 これにて解決としたいと思います。 Private Sub setData() 'データ取得処理 For Each rec As DataRow In dt.Rows '↓この部分を変更 item = New listItem AddHandler item.PropertyChanged, AddressOf item_PropertyChanged '↑この部分を変更 ’以降データ格納処理 Next End Sub
分類:[.NET]