Cradle ha scritto:
non devi far altro che aggiungere un handler da MiaClasse a ogni Rigo che aggiungi (e rimuoverlo quando lo rimuovi) e rilanciare da questo l'evento PropertyChanged di MiaClasse. Per capirci
in MiaClasse:
Public Sub Add(item as Rigo)
AddHandler(Rigo.PropertyChanged, Me.PropertyChangedHandler)
End Sub
Public Sub PropertyChangedHandler(sender as Object, e as PropertyChangedEventArgs)
If Not Me.PropertyChanged Is Nothing Then
Me.PropertyChanged(Sender, e)
End If
End Sub
Come vedi, dentro Rigo non serve nessuna reference a MiaClasse
Credo che aggiungere l'handler da MiaClassse "equivale" a dare a Rigo la reference di MiaClasse (infatti inietti l'indirizzo di Me.PropertyChangedHandler).
Comunque, per evitare incomprensioni, posto il codice:
Public Class MiaClasse
Private _righi As List(Of Rigo)
Private _sommaDiProdotti As Decimal
Public Sub New()
_righi = New List(Of Rigo)
_sommaDiProdotti = 0
End Sub
Public Property righi() As List(Of Rigo)
Get
Return _righi
End Get
Set(ByVal value As List(Of Rigo))
_righi = value
End Set
End Property
Public ReadOnly Property sommaDiProdotti() As Decimal
Get
Return _sommaDiProdotti
End Get
End Property
Protected Sub calcolaSommaDiProdotti()
_sommaDiProdotti = 0
For Each r As Rigo In _righi
_sommaDiProdotti = _sommaDiProdotti + (r.fattore1 * r.fattore2)
Next
End Sub
End Class
Public Class Rigo
Implements INotifyPropertyChanged
Private _fattore1 As Decimal
Private _fattore2 As Decimal
Public Property fattore1() As Decimal
Get
Return _fattore1
End Get
Set(ByVal value As Decimal)
_fattore1 = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("fattore1"))
End Set
End Property
Public Property fattore2() As Decimal
Get
Return _fattore2
End Get
Set(ByVal value As Decimal)
_fattore2 = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("fattore2"))
End Set
End Property
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Private Sub Rigo_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Handles Me.PropertyChanged
' questo codice viene eseguito se cambia fattore1 o fattore2
' e da qui vorrei forzare l'esecuzione di calcolaSommaDiProdotti
End Sub
End Class
Da notare che per brevità non ho implementato INotifyPropertyChanged su MiaClasse. Inoltre, non vorrei implementare IList(Of Rigo) perchè mi sembra quasi inutile. Infatti si presenterebbero 2 scenari:
A)
Dim m as New MiaClasse
Dim r1 as New Rigo
m.Add(r1) ' qui tutto ok gli eventi vengono sollevati
B)
Dim L as new List(of Rigo)
Dim r1 as New Rigo
L.Add(r1)
Dim m as New MiaClasse
m.righi = L ' qui non è possibile settare gli handler: m viene creata dopo
' non uso il metodo Add di MiaClasse, ma quello della List(Of T)
Nello scenario B, avrei evidenza dell'errore solo a runtime.
Questo è il codice per testare il funzionamento desiderato:
Dim m As New MiaClasse
Dim r1 As New Rigo
r1.fattore1 = 1
r1.fattore2 = 2
m.righi.Add(r1)
' ora dovrebbe stampare 2
Console.WriteLine("la somma di prodotti è {0}", m.sommaDiProdotti.ToString)
Dim r2 As New Rigo
r2.fattore1 = 1
r2.fattore2 = 2
m.righi.Add(r2)
' ora dovrebbe stampare 4 = 1*2 + 2*2
Console.WriteLine("la somma di prodotti è {0}", m.sommaDiProdotti.ToString)
m.righi(0).fattore1 = 3
' ora dovrebbe stampare 8 = 3*2 + 1*2
Console.WriteLine("la somma di prodotti è {0}", m.sommaDiProdotti.ToString)
La problematica che mi sto ponendo non è relativa alla web app (forse avrei fatto meglio a postare nel forum .net framework), ma al solo domain model.
Si tratta di implementare una regola del business object: MiaClasse può avere una list(of Rigo) ed espone la somma dei prodotti dei fattori contenuti nei righi.
Ovviamente, potevo mettere un For Each nel Get di sommaDiProdotti e ricalcolarlo ogni volta. Pero' mi sembrava uno spreco di operazioni, specie se sommaDiProdotti è molto acceduto. Conviene ricalcolarlo solo quando serve effettivamente.
Spero che il problema sia piu' chiaro. Sei libero di modificare il codice da me postato.
Qualcun altro si è posto il mio problema e l'ha risolto così:
http://www.codeproject.com/KB/cs/ListOfMutablesWithEvents.aspx?msg=2762342
L'ho testato e funziona, anche se mi sembra un po' macchinoso.
Grazie e scusami se ti sto facendo scervellare :)
Modificato da k4soft il 13 gennaio 2010 01.17 -