WinForms - MVP - Forms Events in Form Interface - vb.net

I am trying to implement MVP in a small WinForms App I am developing.
As known, I need to define an IView interface.
The IView interface should have an event that is fired when the concrete View loads.
This event is already implented in WinForms as the Load() event.
Now in some guides/tutorials I have seen they implemented it like this
Public Interface IView
Event OnPrepareView()
.....
End Interface
Public Class MainForm
Inherits Form
Implements IView
Private Sub Main_Load(sender As Object, e As EventArgs) Handles Me.Load
RaiseEvent OnPrepareView()
End Sub
Public Event OnPrepareView()
End Class
Now I was wondering if its possible to expose directly the Form Load event directly in the interface, so that IView looks like:
Public Interface IView
Event Load()
.....
End Interface
And the Load event is implemented in the Form with it's load event.
If possible how should I do it in VB?
UPDATE
For example for a Property like Iconor Function like Show which are defined in System.Windows.Forms.Form.
I would have an IView:
Public Interface IView
Property Icon as Icon
Sub Show()
End Interface
And then in my concrete implementation
Public Class FooForm
Inherits Form
Implements IView
Public Overloads Property Icon as Icon Implementes IView.Icon
Get
return MyBase.Icon
End Get
Set
MyBase.Icon = value
End Set
Public Overloads Sub Show()
MyBase.Show()
End Sub
End Class
but how can I do for the Form events?
Or should I just declare new Event in IView like:
Public Interface IView
Property Icon as Icon
Sub Show()
Event OnLoad()
End Interface
Public Class FooForm
Inherits Form
Implements IView
....
....
Public Event OnLoad() Implements IView.OnLoad
Private Sub FooForm_Load() Handles Me.Load
RaiseEvent OnLoad()
End Sub
End Class

You should declare the event in the interface, then in the Form implement the interface, then override OnLoad and raise the event. For example:
Public Interface IView
Event Load As EventHandler
End Interface
Public Class Form1
Implements IView
Public Shadows Event Load As EventHandler Implements IView.Load
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
RaiseEvent Load(Me, e)
End Sub
End Class

Related

I want main class event to be raised in supported form

I have public class, with event declared in it.
And have procedure which shows modal form.
The form has buttons, on whichs click I want the main event to be raised. How to achieve this?
for example:
Public class MyClass
Public Event MyEvent(arg as date)
Public Sub ShowForm()
using frm as new frmMyForm
frm.showDialog()
End Using
....
End Class
On forms button click event
RaiseEvent MyClass.MyEvent(Today)
I have passed egzemplar of class as property, but nothing helped.
I have solved problem. I have really created method in the main class with date parameter. In button click I'm calling above method of passed egzemplar with desired argument. and then raising event in a class. it works fine now.
In my situation code is more harder, therefore I provide only a simple example instead.
Public class MyClass
Public Event MyEvent(arg as date)
Public sub FromOtherPlanet(dt as Date)
RaiseEvent MyEvent(dt)
End sub
Public Sub ShowForm()
using frm as new frmMyForm
frm.Egz = Me
frm.showDialog()
End Using
End Sub
....
End Class
in the form
Public class MyForm
dim Temp_Egz as MyClass
public property Egz as Myclass
Get
.......
Set
....
End Property
private sub button1_click.....
egz.FromOtherPlanet(today)
end sub
end class

How to define an Action in an interface

How can I define the StateChangedAction in an interface? I have the same Action on different controls, so I would be cleaner to work with a single interface.
Public class MyControl
Public StateChangedAction As Action(Of ControlState)
Public Sub New()
End Sub
End Class

Remove/Hide Public Controls from Toolbox

I have a problem making a custom control. When I create and build the control is in my toolbox which is kind of what I was after:
Public Class PanelBar
Inherits Panel
Private _mCusBtn As CustomButton
Public Sub New()
InitializeComponent()
_mCusBtn = New CustomButton()
AddHandler _mCusBtn.ButtonClicked, AddressOf CustomButtonClicked
Controls.Add(_mCusBtn)
Public Sub CustomButtonClicked(ByVal btn As CustomButton, ByVal buttonId As Int32)
' Do important stuff here...
End Sub
End Class
However, when It displays in the toolbox this control also displays:
Public Class CustomButton
Inherits Button
Public Property BtnId As Integer
Public Property BtnColor As Color
Public Event ButtonClicked(sender As CustomButton, buttonId As Int32)
Public Sub New()
' Set new property values
End Sub
Private Sub CustomButtonClicked(sender As Object, e As EventArgs) Handles Me.Click
RaiseEvent ButtonClicked(Me, BtnId)
End Sub
End Class
So I have tried setting the CustomButton class to friend to limit the outside access because I do not want this as a control in my toolbox and I get this error: 'btn' cannot expose type 'CustomButton' outside the project through class 'PanelBar'. on the CustomButtonClicked event of the first class.
I'm not sure if this makes sense to want to limit the scope of the controls that help make up my custom control since it is having to access the events on them. To be honest I do not recall one time that I have come across a custom control that doesn't list the controls that make it up, so I am not entirely certain this is going to be possible...but I would really appreciate any advice I can get.
To "hide" a control from the toolbox, use the ToolboxItem attribute:
<ToolboxItem(False)>
Public Class CustomButton
...
If your class inherits from Component rather than Control and you don't want them to show in the form component tray at the bottom use:
<DesignTimeVisible(False)>
Public Class FooBarItem
...

How to update UI when a property change

I'm trying to update my UI when a property in my BL class changes. Please can someone advise the best way to do this in vb.net
Not a really precise question so I will explain the standard way (in my opinion).
Implement the INotifyPropertyChanged interface in your class and handle the PropertyChanged event of your object.
First the the class of the object that contains the property in question:
Public Class MySweetClass
Implements System.ComponentModel.INotifyPropertyChanged
Private _MyProperty As String
Public Property MyProperty As String
Get
Return _MyProperty
End Get
Set(value As String)
_MyProperty = value
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("MyProperty"))
End Set
End Property
Public Event PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
Notice that the PropertyChanged event is raised once the value of the property changes.
In your form handle this event:
Public Class Form1
Private WithEvents MySweetObject As MySweetClass
Private Sub MySweetObject_PropertyChanged(sender As Object, e As System.ComponentModel.PropertyChangedEventArgs) Handles MySweetObject.PropertyChanged
'Update gui here
End Sub
End Class
This lets you update the GUI whenever the value changes.

Shadowing an event handler

I have a two windows forms classes, a base class and a derived class. The base class has an event handler which handles ValueChanged on some component. I have also written a different event handler for the same event on the derived class.
When I create an instance of the derived class and fire the event, I find that both event handlers run (the base class one and then the derived class one). But I want only the handler in the derived class to run.
Is this possible and if so how do I do it?
(This is .NET 3.5)
Thanks!
Edit: Here is what the code looks like (can't post the actual code):
Public Class BaseForm
Inherits System.Windows.Forms.UserControl
(Windows Form Designer Generated Code)
Private WithEvents myControl As New SomeOtherControl
Protected value As String
Private Sub myControl_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles myControl.ValueChanged
value = SomeLogic()
End Sub
End Class
Public Class DerivedForm
Inherits BaseForm
Private WithEvents myControl As New SomeOtherControl
Private Sub myControl_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles myControl.ValueChanged
value = myControl.Value
End Sub
End Class
You can attach multiple handlers to one event so what you are seeing is by design (you have two handlers attached to the same event so they both fire).
That being said there are ways to accomplish what you are trying to do. One way is to move the code out of your base class handler into an overridable method, and then in the derived class override the method. So your base class handler only has 1 line of code,calling the new method you made. If you inherit from the class it will call your overridden method instead.
Public Class BaseForm
Private Sub myControl_ValueChanged() Handles myControl.ValueChanged
DoSomeLogic()
End Sub
Protected Overridable Sub DoSomeLogic()
'original logic here
End Sub
End Class
Public Class ChildForm
Inherits BaseForm
Protected Overrides Sub DoSomeLogic()
'other logic here
End Sub
End Class
I don't believe you can control that.
If it were me, I think I'd intercept the event in the base class, as you are doing, then define ANOTHER event from the base class and raise that event FROM the event handler in the base class.
on return, if the event was handled (presumably by your derived class), then just exit the base event handler, otherwise, proceed with the base event handling.