Anyone?
I know it's not an ES question but I also know there's a lot of experience developers here so any help/advice/pointers would be very much appreciated - even if it's along the lines of "Forget your approach, a much more suitable architecture for an app with a winform AND webform front end would be....".
Anyway, in the hope that what has stopped people replying is a lack of code, here's some... all generated against the standard Northwind db, sample code below is against the Categories table..
Here's the interface for the view:
Code:
Public Interface ICategoriesView
Writeonly Property CategoryID As Nullable(Of System.Int32)
Writeonly Property CategoryName As System.String
Writeonly Property Description As System.String
Writeonly Property Picture As System.Byte()
Sub RegisterChangeRequestListener(Of T)(ByVal propertyName As String, ByVal handler As EventHandler(Of PropertyChangeRequestEventArgs(Of T)))
Sub UnRegisterChangeRequestListener(Of T)(ByVal propertyName As String, ByVal handler As EventHandler(Of PropertyChangeRequestEventArgs(Of T)))
End Interface
Here's the concrete (view) implementation for the above interface:
Code:
#Region "Imports"
Imports System
Imports System.Collections.Generic
Imports Northwind.MVC
#End Region
Partial Public Class CategoriesView
Implements ICategoriesView
#Region "Constructors"
Public Sub New()
InitializeComponent()
m_changeRequestedEvents = New ChangeRequestEvents(Me)
End Sub
#End Region
#Region "Member Variables"
Private m_changeRequestedEvents As ChangeRequestEvents
#End Region
#Region "ICategoriesView Members"
Public Writeonly Property CategoryID As Nullable(Of System.Int32) Implements ICategoriesView.CategoryID
Set(ByVal value as Nullable(Of System.Int32))
CategoryIDLabel.Text = value
End Set
End Property
Public Writeonly Property CategoryName As System.String Implements ICategoriesView.CategoryName
Set(ByVal value as System.String)
CategoryNameTextbox.Text = value
End Set
End Property
Public Writeonly Property Description As System.String Implements ICategoriesView.Description
Set(ByVal value as System.String)
DescriptionTextbox.Text = value
End Set
End Property
Public Writeonly Property Picture As System.Byte() Implements ICategoriesView.Picture
Set(ByVal value as System.Byte())
'TODO: set control to show value of Picture
' control type would be: Unknown/undecided Windows control
' System type is: System.Byte()
End Set
End Property
Public Sub RegisterChangeRequestListener(Of T)(ByVal propertyName As String, ByVal handler As EventHandler(Of PropertyChangeRequestEventArgs(Of T))) Implements ICategoriesView.RegisterChangeRequestListener
m_changeRequestedEvents.RegisterListener(Of T)(propertyName, handler)
End Sub
Public Sub UnRegisterChangeRequestListener(Of T)(ByVal propertyName As String, ByVal handler As EventHandler(Of PropertyChangeRequestEventArgs(Of T))) Implements ICategoriesView.UnRegisterChangeRequestListener
m_changeRequestedEvents.UnRegisterListener(Of T)(propertyName, handler)
End Sub
#End Region
End Class
This snippet would be in, say, the event handler for a "Save changes" button click:
Code:
Private Sub SaveChanges_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveChangesButton.Click
m_changeRequestedEvents.Fire(Of String)("CategoryName", CategoryNameTextbox.Text)
'......etc for the rest of the properties....
End Sub
Here's the controller base class:
Code:
Public MustInherit Class ControllerBase(Of TModel As {Northwind.Model.BusinessObjects.EntityBase, New}, TView)
Implements IDisposable
#Region "Member Variables"
Protected _view As TView
Protected _model As New TModel
#End Region
#Region "Abstract Methods"
Protected MustOverride Sub WireEvents()
Protected MustOverride Sub UnwireEvents()
Protected MustOverride Sub SetViewState()
#End Region
#Region "Methods"
Public Overridable Sub Initialize(ByVal model As TModel, ByVal view As TView)
If _model IsNot Nothing OrElse _view IsNot Nothing Then
UnwireEvents()
End If
_model = model
_view = view
SetViewState()
WireEvents()
End Sub
#End Region
#Region "Properties"
Public ReadOnly Property Model() As TModel
Get
Return _model
End Get
End Property
Public ReadOnly Property View() As TView
Get
Return _view
End Get
End Property
#End Region
#Region "IDisposable Members"
Public Sub Dispose() Implements IDisposable.Dispose
UnwireEvents()
End Sub
#End Region
End Class
And here's the (inherited) Controller
Code:
#Region "Imports"
Imports System
Imports System.Collections.Generic
Imports Northwind.Model.BusinessObjects
#End Region
Public Class CategoriesController
Inherits ControllerBase(Of Categories, ICategoriesView)
Public Sub New(ByVal model As Categories, ByVal view As ICategoriesView)
Initialize(model, view)
End Sub
Protected Overrides Sub WireEvents()
AddHandler model.PropertyChanged, AddressOf model_PropertyChanged
view.RegisterChangeRequestListener(Of Nullable(Of System.Int32))("CategoryID", AddressOf View_OnCategoryIDChangeRequest)
view.RegisterChangeRequestListener(Of System.String)("CategoryName", AddressOf View_OnCategoryNameChangeRequest)
view.RegisterChangeRequestListener(Of System.String)("Description", AddressOf View_OnDescriptionChangeRequest)
view.RegisterChangeRequestListener(Of System.Byte())("Picture", AddressOf View_OnPictureChangeRequest)
End Sub
Protected Overrides Sub UnWireEvents()
RemoveHandler model.PropertyChanged, AddressOf model_PropertyChanged
view.UnRegisterChangeRequestListener(Of Nullable(Of System.Int32))("CategoryID", AddressOf View_OnCategoryIDChangeRequest)
view.UnRegisterChangeRequestListener(Of System.String)("CategoryName", AddressOf View_OnCategoryNameChangeRequest)
view.UnRegisterChangeRequestListener(Of System.String)("Description", AddressOf View_OnDescriptionChangeRequest)
view.UnRegisterChangeRequestListener(Of System.Byte())("Picture", AddressOf View_OnPictureChangeRequest)
End Sub
Private Sub Model_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs)
Select Case e.PropertyName
Case "CategoryID"
view.CategoryID = model.CategoryID
Case "CategoryName"
view.CategoryName = model.CategoryName
Case "Description"
view.Description = model.Description
Case "Picture"
'Handle the Picture here - i.e. view.Picture = model.Picture
Case Else
Throw New ArgumentException("Property not handled: " & e.PropertyName)
End Select
End Sub
Private Sub View_OnCategoryIDChangeRequest(ByVal sender As Object, ByVal args As PropertyChangeRequestEventArgs(Of Nullable(Of System.Int32)))
model.CategoryID = args.RequestedValue
End Sub
Private Sub View_OnCategoryNameChangeRequest(ByVal sender As Object, ByVal args As PropertyChangeRequestEventArgs(Of System.String))
model.CategoryName = args.RequestedValue
End Sub
Private Sub View_OnDescriptionChangeRequest(ByVal sender As Object, ByVal args As PropertyChangeRequestEventArgs(Of System.String))
model.Description = args.RequestedValue
End Sub
Private Sub View_OnPictureChangeRequest(ByVal sender As Object, ByVal args As PropertyChangeRequestEventArgs(Of System.Byte()))
model.Picture = args.RequestedValue
End Sub
Protected Overrides Sub SetViewState()
view.CategoryID = model.CategoryID
view.CategoryName = model.CategoryName
view.Description = model.Description
'view.Picture = model.Picture
End Sub
End Class
Anyway, as I said in my initial post, I'm trying to get my head around the pattern and how to implement it/deal with collections etc - or even whether this is the right path to go down - I'm open to ideas as always!
Cheers all, and apologies for yet another mega-long post!
Martin