Is there an event in Win Forms that can fire when the count of items in ListView change?
I got this link helpful a little but I cannot understand the answer as it is in c#.
Reffered Link
The answer in the link says about making some private function I guess..
If there is any event available than it would be more helpful than making a function or something.
Any help is greatfully accepted..
Option 1
You can put the logic of add/remove in specific methods and write the codes there; the codes that you want to run when count of items changed.
Option 2
You can inherit from ListView and override WndProc and raise a custom ItemsCountChanged event when receiving LVM_INSERTITEM, LVM_DELETEITEM and DELETEALLITEMS.
Public Class ListViewEx
Inherits ListView
Private Const LVM_FIRST As Integer = &H1000
Private Const LVM_INSERTITEM As Integer = LVM_FIRST + 77
Private Const LVM_DELETEITEM As Integer = LVM_FIRST + 8
Private Const DELETEALLITEMS As Integer = LVM_FIRST + 9
Public Event ItemsCountChanged As EventHandler
Protected Overridable Sub OnItemsCountChanged(ByVal e As EventArgs)
RaiseEvent ItemsCountChanged(Me, e)
End Sub
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
Select Case m.Msg
Case LVM_INSERTITEM, LVM_DELETEITEM, DELETEALLITEMS
OnItemsCountChanged(EventArgs.Empty)
End Select
End Sub
End Class
Then you can subscribe for the event and do what you need:
Private Sub listView1_ItemsCountChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles listView1.ItemsCountChanged
'Do stuff here
End Sub
Note
You can enhance the above implementation and also create ItemInserted or ItemDeleted events.
You can extract more information from mesages, for example you can find inserted or deleted item index and include in event args.
For cases that you don't want to inherit from ListView you can do the same job using a NativeWindow and passing an existing ListView to the native window and assign list view handle to the window.
I know i'm late but this is by far the best solution:
Private Sub ListView1_Invalidated(sender As Object, e As EventArgs) Handles ListView1.Invalidated
nbr.Text = ListView1.Items.Count 'nbr.text is a Label Control
End Sub
Related
Hi I'm implementing a custom menu in a panel like this image (link) below..
heres the link http://i.imgur.com/5OlRk9c.png
My question is, how can I detect that the user clicks on another part of my form excepts the menu panel and buttons(inside the red circle).
I already used the LostFocus event but nothing happens.
Please help.
You can trap mouse messages before they get routed to the controls via IMessageFilter. Then you can check to see if the cursor position is inside or outside the bounds of your panel. Here's a simple example with Panel1:
Public Class Form1
Private WithEvents filter As New MyFilter
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Application.AddMessageFilter(filter)
End Sub
Private Sub filter_LeftClick() Handles filter.LeftClick
Dim rc As Rectangle = Panel1.RectangleToScreen(Panel1.ClientRectangle)
If Not rc.Contains(Cursor.Position) Then
Debug.Print("Click outside of Panel1")
End If
End Sub
Private Class MyFilter
Implements IMessageFilter
Public Event LeftClick()
Private Const WM_LBUTTONDOWN As Integer = &H201
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
Select Case m.Msg
Case WM_LBUTTONDOWN
RaiseEvent LeftClick()
End Select
Return False
End Function
End Class
End Class
Hey and sorry for another strange question...
I have 25 UserControls with a Start_Button on each of them - this Start_Button can either be Visible or not depending on whether the UserControl is active. On my form1 I have a Start_All button.
I would like to simulate a click of all the UserControl's Start_Buttons which are visible only.
Instead of simulating click-events expose a method for the start-functionality and call this method from the Start_Button.Click-event. Then you can use this method from wherever you want. On this way your code remains readable and reusable.
You should also provide an Active property in your UserControl which you can simply link to your start-button's Visible-property.
Presuming that the user-controls are in a container-control like Panel:
Public Sub StartAll()
Dim allActiveUserControls =
From uc In controlPanel.Controls.OfType(Of MyUserControlType)()
Where uc.Active
For Each uc In allActiveUserControls
uc.Start()
Next
End Sub
Here is an example for the Active property:
Public Property Active As Boolean
Get
Return StartButton.Visible
End Get
Set(value As Boolean)
StartButton.Visible = value
End Set
End Property
and here are the Start method and the event-handlers:
Public Sub Start()
' Do Something ... '
End Sub
Private Sub StartButton_Click(sender As System.Object, e As System.EventArgs) Handles StartButton.Click
Start()
End Sub
Private Sub Start_All_Click(sender As System.Object, e As System.EventArgs) Handles Start_All.Click
StartAll()
End Sub
I have a class A which contains 2 user controls declared as
Friend WithEvents CustInfo1 As WindowsApplication1.CustInfo
Friend WithEvents ServiceLocation1 As WindowsApplication1.ServiceLocation
Both have textBoxes. If value of textBoxA in custInfo1 changes then how can I make value of textBoxB in SeviceLocation1 also change
I will be most thankful if anyone can help me.
Thanks
You need to do the following:
Inside the CustInfo user control, you need to write code inside the textBoxA Changed event that raises an event from the CustInfo user control (e.g. TextBoxChanged event). RaiseEvent statement
Inside the ServiceLocation user control, create a public property getter and setter for whatever your textBoxB.Text is
On the form that contains both user controls, create code in the new CustInfo TextBoxChanged event and set the new property on the ServiceLocation1 user control.
All controls (also custom controls) have the property Controls, through which you can access the (sub) controls of that control. Now you can retrieve your textbox by calling the .Item(key) method on it. Then you can assign a event handler to it in your form or class.
Dim key As String = "textBoxA" 'Or simply the name of that TextBox in your CustInfo
Dim textboxA As TextBox = CustInfo1.Controls.Item(key)
AddHandler textBoxA.TextChanged, AddressOf mytextchangedhandler
Where that mytextchangedhandler handles the TextChanged event for that TextBox.
Personally I don't like this method too much, as you are relying on knowing either the name of the TextBox or the index in the Controls list of your usercontrol.
I would definitely go for the option to create your own event on your usercontrol. It is quite easy to do even! Below how to do it. In the code behind of your usercontrol, you'll have to add an event declaration:
Event MyTextBoxChanged(sender As Object, e As EventArgs)
Now we'll have to raise it, we do this by implementing the TextChanged event of the TextBoxA in your usercontrol (as you explained you wanted to do):
Private Sub TextBoxA_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBoxA.TextChanged
RaiseEvent MyTextBoxChanged(Me, EventArgs.Empty)
End Sub
Now we can simply implement this event (MyTextBoxChanged) in your Form as follows:
Private Sub CustInfo1_MyTextBoxChanged(sender As System.Object, e As System.EventArgs) Handles CustInfo1.MyTextBoxChanged
' Do something
End Sub
Obviously we still need to get the updated text, now we can create our own EventArgs that will give us the new (and/or old value) as you will want to have. We simply can inherit the System.EventArgs class and add some properties (for example a property OldText that holds the old text value and a property NewText that holds the new text value):
Public Class MyEventArgs
Inherits System.EventArgs
Private _OldText As String
Public ReadOnly Property OldText() As String
Get
Return _OldText
End Get
End Property
Private _NewText As String
Public ReadOnly Property NewText() As String
Get
Return _NewText
End Get
End Property
Public Sub New(oldText As String, newText As String)
_OldText = oldText
_NewText = newText
End Sub
End Class
Now we have to change the event definition and raising to use the MyEventArgs:
Event MyTextBoxChanged(sender As Object, e As MyEventArgs)
Private Sub TextBoxA_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBoxA.TextChanged
RaiseEvent MyTextBoxChanged(Me, New MyEventArgs(TextBoxA.Text))
End Sub
And also change the implementation in your Form:
Private Sub CustInfo1_MyTextBoxChanged(sender As System.Object, e As MyEventArgs) Handles CustInfo1.MyTextBoxChanged
MessageBox.Show(e.Text)
End Sub
More information about events can be found on our favorite spot MSDN.
I've a vb .net winform that is show by others forms. I've frmA.vb, frmB.vb, frmC.vb and frmD.vb.
This all forms can call frmItem.vb.
frmItem.vb allows the user to select an item from a Database, this item is sent by calling a Set Property on the parent.
i.e.
I open frmA, click on button (something like:)
fi = new frmItem(frmA) 'frmItem has 4 New() methods, frmA.. b... c and d
'i need to pass the correct parent.
fi.showModal()
So, when i add an item, it calls
fA.addItem(item_id)
It works OK, my doubt is about optimization, because i've duplicated frmItem; one copy managed frmA and frmB, and the other one, frmC and frmD.
i.e.
in frmItem1 when i've to sent the item, i use:
private fB as frmB
private fA as frmA
if parentFrmA is nothing then
'Is frmB
fB.addItem(item_id)
else
'Is frmA
fA.addItem(item_id)
end if
And, on frmItem2:
private fC as frmC
private fD as frmD
if parentFrmC is nothing then
'Is frmD
fD.addItem(item_id)
else
'Is frmC
fC.addItem(item_id)
end if
If i modify frmItem1, i've to modify frmItem2 and viceversa, because they should look and act like one.
All four forms, have the same Set Property, but like they're differents forms, i can't use a unique Form class in frmItem.
Is the posibility that one form, can manage multi parents in an easy way??
If you need more info, let me know. Thanks
I can't completely follow your example since, well, I think it's just hard to follow.
But in general, it sounds like these child forms should just be raising an event that the parent form is listening for. That way, you can separate your concerns a bit and not hardcode these dependencies.
You can try making your own EventArgs class to follow best practices:
Public Class ChildFormEventArgs
Inherits EventArgs
Private _ItemID As Integer
Public Sub New(ByVal itemID As Integer)
_ItemID = itemID
End Sub
ReadOnly Property ItemID() As Integer
Get
Return _ItemID
End Get
End Property
End Class
Your child forms would have a public event and you would raise it when ever this "added" thing happens:
Public Class Form2
Public Event ItemAdded(ByVal sender As Object, ByVal e As ChildFormEventArgs)
Private _ItemID as Integer
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
RaiseEvent ItemAdded(Me, New ChildFormEventArgs(_ItemID))
End Sub
End Sub
And then your parent form is the one listening and can act accordingly:
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
Using testForm As New Form2()
AddHandler testForm.ItemAdded, AddressOf ChildForm_ItemAdded
testForm.ShowDialog(Me)
RemoveHandler testForm.ItemAdded, AddressOf ChildForm_ItemAdded
End Using
End Sub
Private Sub ChildForm_ItemAdded(ByVal sender As Object, ByVal e As ChildFormEventArgs)
'// do something here.
'// sender is the child form that called it
'// e is the event arguments that contains the ItemID value
End Sub
Very recently, I was working on a custom button, in which I had to capture the event of the button, and depending on the certain conditions, either I'll block the event or pass it on the form containing my custom button.
Here is prototype of the code I was working on:
Public Class MyCustomButton
Inherits Windows.Forms.Button
Private Sub Me_Clicked(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Click
Dim i As Integer = MsgBox("Are you sure you want to perform the operation?", MsgBoxStyle.YesNoCancel, "MyApp")
If Not i = 6 Then
'Cancel the event
Else
'Continue with the event
End If
End Sub
End Class
Now, I do not have any idea how to block the event and not allow it to pass if the users opts for "No" in the given example.
Any suggestions?
You need to override the OnClick event:
Public Class MyCustomButton
Inherits Button
Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
Dim i As Integer = MsgBox("Are you sure you want to perform the operation?", MsgBoxStyle.YesNoCancel, "MyApp")
If Not i = 6 Then
'Cancel the event
Else
MyBase.OnClick(e)
End If
End Sub
End Class