I have a Generic List, for instance: Public MyPersonnesDeContact As New
System.Collections.Generic.List(Of clsPersonne)
My clsPersonne raises some events, and I want to be able to handle these
events. The problem is: when using the WithEvents (Public WithEvents
MyPersonnesDeContact As New System.Collections.Generic.List(Of clsPersonne))
I get an error, saying "'WithEvents' variable does not raise any events.".
Does anybody know how I could be able to handle events that happens in the
intances of the class in my Generic.List?
Any help, hints, workarounds etc would be really appreciated!
Thanks a lot in advance,
Pieter
Are you sure that your class raises "Public" events.
Fist guess
:-)
Cor
"Cor Ligthert [MVP]" <notmyfi...@planet.nl> wrote in message
news:%23huyOE%23zFH...@TK2MSFTNGP10.phx.gbl...
----------------
-Atul, Sky Software http://www.ssware.com
Shell MegaPack For .Net & ActiveX
Windows Explorer GUI Controls
&
Quick-Launch Like Appbars, MSN/Office2003 Style Popups,
System Tray Icons and Shortcuts/Internet Shortcuts
----------------
"DraguVaso" <pieter...@hotmail.com> wrote in message
news:e5MjPA%23zFH...@TK2MSFTNGP15.phx.gbl...
Try something like this.
Public Class Form1
Dim myList As New List(Of TestClass)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
For x As Integer = 0 To 10
Dim ct As New TestClass
ct.TestItem = x.ToString
AddHandler ct.ItemAdded, AddressOf ItemAddedEvent
myList.Add(ct)
Next
End Sub
Public Sub ItemAddedEvent(ByVal sender As Object, ByVal e As EventArgs)
MessageBox.Show("Item Added")
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
myList(5).TestItem = "Changed"
End Sub
End Class
Public Class TestClass
Public Event ItemAdded(ByVal sender As Object, ByVal e As EventArgs)
Dim mstrTest As String
Public Property TestItem() As String
Get
Return mstrTest
End Get
Set(ByVal value As String)
mstrTest = value
RaiseEvent ItemAdded(Me, New EventArgs)
End Set
End Property
End Class
Ken
-------------------
"DraguVaso" <pieter...@hotmail.com> wrote in message
news:e5MjPA%23zFH...@TK2MSFTNGP15.phx.gbl...
... which is true. It's not the list object which is raising the events.
The objects stored in/referenced by the list are raising events. Thus
you'll have to connect event handlers to the items instea of connecting them
to the list. You can use the 'AddHandler' statement in order to add a
handler to an item's event. If the events are implemented properly, the
'sender' parameter of the event handler contains a reference to the object
which raised the event -- which is especially useful when connecting the
same event handler to the events of more than one object.
--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://classicvb.org/petition/>
thanks a lot,
Pieter
"Herfried K. Wagner [MVP]" <hirf-spa...@gmx.at> wrote in message
news:e0xmpe%23zFH...@TK2MSFTNGP10.phx.gbl...
It sounds like you want List(Of T) to raise events based on the objects it
contains. What I normally do is derive a class from the base collection
(List(Of T) in your case), then override the "add" and "remove" of the
collection to use AddHandler & RemoveHandler on each object being added or
removed from my collection, so that the collection can raise the event that
the individual items raise...
Something like (.NET 1.1 sample):
Public Class Person
Public Event NameChanged As EventHandler
Private m_name As String
Public Property Name() As String
Get
Return m_name
End Get
Set(ByVal value As String)
m_name = value
OnNameChanged(EventArgs.Empty)
End Set
End Property
Protected Overridable Sub OnNameChanged(ByVal e As EventArgs)
RaiseEvent NameChanged(Me, e)
End Sub
Public Overrides Function ToString() As String
Return "Person(" & m_name & ")"
End Function
End Class
Public Class PersonCollection
'Inherits CollectionBase
Inherits ArrayList
Public Event NameChanged As EventHandler
Public Overrides Function Add(ByVal value As Object) As Integer
Dim person As person = DirectCast(value, person)
AddHandler person.NameChanged, AddressOf Person_NameChanged
Return MyBase.Add(value)
End Function
Public Overrides Sub Remove(ByVal value As Object)
Dim person As person = DirectCast(value, person)
RemoveHandler person.NameChanged, AddressOf Person_NameChanged
MyBase.Remove(value)
End Sub
Private Sub Person_NameChanged(ByVal sender As Object, ByVal e As
EventArgs)
' TODO: Consider defining a new EventArgs class that includes
person
RaiseEvent NameChanged(sender, e)
End Sub
End Class
Private Shared WithEvents people As New PersonCollection
Private Shared Sub people_NameChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles people.NameChanged
Debug.WriteLine(sender, "NameChanged")
End Sub
Public Shared Sub Main()
Dim person1 As New Person
Dim person2 As New Person
Dim person3 As New Person
people.Add(person1)
people.Add(person2)
people.Add(person3)
person1.Name = "Person 1"
person2.Name = "Person 2"
person3.Name = "Person 3"
people.Remove(person3)
person3.Name = String.Empty
End Sub
You may also need to override Insert & other methods...
NOTE: In practice I would have PersonCollection.NameChanged use an EventArgs
derived classt that included the Person object that changed, then the sender
parameter to the event would be the PersonCollection itself...
--
Hope this helps
Jay [MVP - Outlook]
T.S. Bradley - http://www.tsbradley.net
"DraguVaso" <pieter...@hotmail.com> wrote in message
news:e5MjPA%23zFH...@TK2MSFTNGP15.phx.gbl...
"Jay B. Harlow [MVP - Outlook]" <Jay_Har...@tsbradley.net> wrote in
message news:eCfBHxC...@TK2MSFTNGP10.phx.gbl...
It uses System.Collections.ObjectModel.Collection(Of T) for the base of the
collection. Collection(Of T) is the replacement for CollectionBase, just as
List(Of T) is the replacement for ArrayList.
---x--- cut here ---x---
'
' Copyright © 2005, Jay B. Harlow, All Rights Reserved.
'
Option Strict On
Option Explicit On
Public Class Person
Public Event NameChanged As EventHandler
Private ReadOnly m_id As Integer
Private m_name As String
Public Sub New(ByVal id As Integer)
m_id = id
End Sub
Public ReadOnly Property Id() As Integer
Get
Return m_id
End Get
End Property
Public Property Name() As String
Get
Return m_name
End Get
Set(ByVal value As String)
m_name = value
OnNameChanged(EventArgs.Empty)
End Set
End Property
Protected Sub OnNameChanged(ByVal e As EventArgs)
RaiseEvent NameChanged(Me, e)
End Sub
Public Overrides Function ToString() As String
Return "Person(" & m_id & ", " & m_name & ")"
End Function
End Class
---x--- cut here ---x---
'
' Copyright © 2005, Jay B. Harlow, All Rights Reserved.
'
Option Strict On
Option Explicit On
Public Class PersonCollection
Inherits System.Collections.ObjectModel.Collection(Of Person)
Public Event PersonNameChanged As EventHandler(Of
PersonNameChangedEventArgs)
Protected Overrides Sub ClearItems()
For Each item As Person In Me
RemoveHandler item.NameChanged, AddressOf OnNameChanged
Next
MyBase.ClearItems()
End Sub
Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As
Person)
AddHandler item.NameChanged, AddressOf OnNameChanged
MyBase.InsertItem(index, item)
End Sub
Protected Overrides Sub RemoveItem(ByVal index As Integer)
Dim item As Person = Me(index)
RemoveHandler item.NameChanged, AddressOf OnNameChanged
MyBase.RemoveItem(index)
End Sub
Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As
Person)
Dim itemOriginal As Person = Me(index)
RemoveHandler itemOriginal.NameChanged, AddressOf OnNameChanged
AddHandler item.NameChanged, AddressOf OnNameChanged
MyBase.SetItem(index, item)
End Sub
Private Sub OnNameChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim args As New PersonNameChangedEventArgs(DirectCast(sender,
Person))
OnPersonNameChanged(args)
End Sub
Protected Overridable Sub OnPersonNameChanged(ByVal e As
PersonNameChangedEventArgs)
RaiseEvent PersonNameChanged(Me, e)
End Sub
End Class
---x--- cut here ---x---
'
' Copyright © 2005, Jay B. Harlow, All Rights Reserved.
'
Option Strict On
Option Explicit On
Public Class PersonNameChangedEventArgs
Inherits EventArgs
Private ReadOnly m_person As Person
Public Sub New(ByVal person As Person)
m_person = person
End Sub
Public ReadOnly Property Person() As Person
Get
Return m_person
End Get
End Property
End Class
---x--- cut here ---x---
'
' Copyright © 2005, Jay B. Harlow, All Rights Reserved.
'
Option Strict On
Option Explicit On
Public Module MainModule
Private WithEvents people As New PersonCollection
Public Sub Main()
Dim person1 As New Person(1)
Dim person2 As New Person(2)
Dim person3 As New Person(3)
people.Add(person1)
people.Add(person2)
people.Add(person3)
person1.Name = "Person 1"
person2.Name = "Person 2"
person3.Name = "Person 3"
people.Remove(person3)
person3.Name = String.Empty
people(0) = person3
person1.Name = String.Empty
person3.Name = "Jay"
people.Clear()
person1.Name = String.Empty
person2.Name = String.Empty
person3.Name = String.Empty
End Sub
Private Sub People_PersonNameChanged(ByVal sender As Object, ByVal e As
PersonNameChangedEventArgs) Handles people.PersonNameChanged
Debug.WriteLine(e.Person, "Person Name Changed")
End Sub
End Module
---x--- cut here ---x---
--
Hope this helps
Jay [MVP - Outlook]
T.S. Bradley - http://www.tsbradley.net
"DraguVaso" <pieter...@hotmail.com> wrote in message
news:OUwX$hJ0FH...@TK2MSFTNGP12.phx.gbl...
| Thanks! That's a great idea! :-)
|
| "Jay B. Harlow [MVP - Outlook]" <Jay_Har...@tsbradley.net> wrote in
| message news:eCfBHxC...@TK2MSFTNGP10.phx.gbl...
| > Pieter,
| > As Herfreid stated, your clsPersonne raises events List(Of T) does not.
| >
| > It sounds like you want List(Of T) to raise events based on the objects
it
| > contains. What I normally do is derive a class from the base collection
| > (List(Of T) in your case), then override the "add" and "remove" of the
| > collection to use AddHandler & RemoveHandler on each object being added
or
| > removed from my collection, so that the collection can raise the event
| > that
| > the individual items raise...
| >
<<snip>>
Just one thing I've been googling around for, but didn't find (and I guess
it's not possible): In my case I use the my clsBaseClass instead of Person,
because I want to make one type of List which I can use with all my
different types of classes (which inherits all of clsBaseClass). But with
your solution I can make a List, and add first a clsAdress, and then a
clsPerson, which shouldn't be possible with a genric List. But I guess it
just isn't possible...
But thanks a lot anyways for the great help and sample that helped me a lot!
Pieter
"Jay B. Harlow [MVP - Outlook]" <Jay_Har...@tsbradley.net> wrote in
message news:eS2q4BO0...@TK2MSFTNGP09.phx.gbl...
Any idea how to get around this?
Thanks a lot in advance,
Pieter
"DraguVaso" <pieter...@hotmail.com> wrote in message
news:uygK62u0...@TK2MSFTNGP09.phx.gbl...
The sample code:
Public Class clsBaseList(Of T As clsBaseClass)
Inherits System.Collections.Generic.List(Of T)
'property's, methods etc...
'...
#Region "List Methods"
Protected Overridable Sub OnPropertyChanged(ByVal sender As Object,
ByVal e As HasChangesEventArgs)
'always...
RaiseEvent HasChangesChanged(Me, e)
End Sub
Public Shadows Sub Add(ByVal item As T)
AddHandler item.HasChangesChanged, AddressOf Me.OnPropertyChanged
MyBase.Add(item)
End Sub
Public Shadows Sub Insert(ByVal index As Integer, ByVal item As T)
AddHandler item.HasChangesChanged, AddressOf Me.OnPropertyChanged
MyBase.Insert(index, item)
End Sub
Public Shadows Sub Clear()
For Each item As clsBaseClass In Me
RemoveHandler item.HasChangesChanged, AddressOf
OnPropertyChanged
Next
MyBase.Clear()
End Sub
Public Shadows Function Remove(ByVal item As T) As Boolean
RemoveHandler item.HasChangesChanged, AddressOf OnPropertyChanged
Return MyBase.Remove(item)
End Function
Public Shadows Sub RemoveAt(ByVal index As Integer)
RemoveHandler MyBase.Item(index).HasChangesChanged, AddressOf
OnPropertyChanged
MyBase.RemoveAt(index)
End Sub
'very import, otherwise it will return objects of clsBaseClass, and not
object of T...
Default Public Shadows Property Item(ByVal index As Integer) As T
Get
Return MyBase.Item(index)
End Get
Set(ByVal value As T)
AddHandler value.HasChangesChanged, AddressOf
Me.OnPropertyChanged
MyBase.Item(index) = value
End Set
End Property
#End Region
End Class
"DraguVaso" <pieter...@hotmail.com> wrote in message
news:e5MjPA%23zFH...@TK2MSFTNGP15.phx.gbl...
However! I would strongly recommend using a collection such as
System.Collections.ObjectModel.Collection(Of T) as a starting point instead
of List(Of T). As Collection(Of T) is designed to be inherited from, where
as List(Of T) is not.
http://msdn2.microsoft.com/en-us/library/ms132397(en-US,VS.80).aspx
Using Shadows to design a derived class can be very problematic at best, as
Shadows is anti-Polymorphic, you need to use Overrides for Polymorphic
behaving.
Consider the following:
Dim list As List(Of Person) = New clsBaseList(Of Person)
list.Add(New Person(...))
clsBaseList.Add will not be called as you Shadowed List(Of T).Add. Seeing as
you have a List(Of T) variable, List(Of T).Add will be called. If you have a
clsBaseList(Of T) variable, then clsBaseList(Of T).Add will be called.
If you Override List(Of T).Add then it would be polymorphic & clsBaseList(Of
T).Add will be called above.
--
Hope this helps
Jay [MVP - Outlook]
T.S. Bradley - http://www.tsbradley.net
"DraguVaso" <pieter...@hotmail.com> wrote in message
news:%23w0OKRw...@TK2MSFTNGP14.phx.gbl...