Problems with Custom DataGridViewRowCollection - vb.net

I am currently working on a multi thread project. The idea is to implement the threat security into my own custom controls. Now I want to override properties of the DataGridViewRowCollection such as the DataGridView.Rows.Add() and DataGridView.Rows.Remove(row as DataGridViewRow) with my code for the threat security.
My idea was to use an own DataGridViewRowCollection XRowCollection instead of the basic DataGridViewRowCollection. When I try to override the Rows property, I get the compiler message:
"Public Overrides ReadOnly Property Rows As XRowCollection" and
"Public Shadows Property Rows As
System.Windows.Forms.DataGridViewRowCollection" cannot overload each
other because they differ only by return types
I would be thankful for any solution or any alternate ideas to implement the threat secure code directly in my cutsom contorl.
Public Class XDataGridView
Inherits System.Windows.Forms.DataGridView
Private _Rows As XRowCollection
Public Overrides ReadOnly Property Rows As XRowCollection
Get
If _Rows Is Nothing Then
_Rows = New NoxRowCollection(Me)
End If
Return _Rows
End Get
End Property
End Class
Public Class XRowCollection
Inherits DataGridViewRowCollection
Public Sub New(dataGridView As XDataGridView)
MyBase.New(CType(dataGridView, DataGridView))
End Sub
Private Delegate Sub RowsRemoveCallback(DataGridViewRow As System.Windows.Forms.DataGridViewRow)
Public Shadows Sub Remove(DataGridViewRow As System.Windows.Forms.DataGridViewRow)
If MyBase.DataGridView.InvokeRequired Then
Dim d As New RowsRemoveCallback(AddressOf Remove)
MyBase.DataGridView.Invoke(d, New Object() {DataGridViewRow})
Else
Me.DataGridView.Rows.Remove(DataGridViewRow)
End If
End Sub
End Class

Related

Is there a Singleton that raises events?

I have a singleton class, but I want its object to be able to raise events.
My current singleton code is as follows:
Private Shared ReadOnly _instance As New Lazy(Of WorkerAgent)(Function() New _
WorkerAgent(), LazyThreadSafetyMode.ExecutionAndPublication)
Private Sub New()
End Sub
Public Shared ReadOnly Property Instance() As WorkerAgent
Get
Return _instance.Value
End Get
End Property
Whenever I change ReadOnly _instance As New.. into ReadOnly WithEvents _instance As New...
I get an error saying ReadOnly is not valid on a WithEvents deceleration
Although I can create the instance in the property itself, but I liked the above code because it is using .NET Lazy keyword which probably have great multithreading benefits.
This isn't an answer to your question as asked but it demonstrates why that question doesn't make sense. It also requires a fair chunk of code so posting in a comment wasn't really an option. This is how your singleton class would raise events, i.e. just like any other class, and how a consumer would handle those events, i.e. just like for any other type.
Singleton:
Public Class WorkerAgent
Private Shared ReadOnly _instance As New Lazy(Of WorkerAgent)
Private _text As String
Public Shared ReadOnly Property Instance As WorkerAgent
Get
Return _instance.Value
End Get
End Property
Public Property Text As String
Get
Return _text
End Get
Set
If _text <> Value Then
_text = Value
OnTextChanged(EventArgs.Empty)
End If
End Set
End Property
Public Event TextChanged As EventHandler
Private Sub New()
End Sub
Protected Overridable Sub OnTextChanged(e As EventArgs)
RaiseEvent TextChanged(Me, e)
End Sub
End Class
Note that the instance event is raised when the instance property changes, just as for any other type, singleton or not.
Consumer:
Public Class Form1
Private WithEvents agent As WorkerAgent = WorkerAgent.Instance
Private Sub agent_TextChanged(sender As Object, e As EventArgs) Handles agent.TextChanged
'...
End Sub
End Class
The field that the single instance is assigned to is where WithEvents gets used. As your error message states, that field cannot be declared ReadOnly too. If they want a ReadOnly field then they need to use AddHandler to handle events.

Best way to expose an object with read-only properties only

I can't find an answer to my question so I'm asking a new one.
I have an object where I want to fill it's properties from another class in the same solution. But the object should expose read-only properties only so the outside-caller can't see nor access the setter (cause there is no setter).
What is the best way to fill the internal backing variables from the same solution? I know I could do it in the constructor but I want to be able to set the variables after creating the object.
Sorry for my weird explaination, maybe a bit of code could help.
This is what I'm doing now:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
'Could use this, but don't want to...
Protected Friend Sub New(foo As String)
End Sub
Friend _foo As String
Public ReadOnly Property Foo As String
Get
Return _foo
End Get
End Property
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject._foo = "bar"
'Could use this, but don't want to...want to access properties directly.
Dim roObject2 As New ReadonlyObject("bar")
End Sub
End Class
With this, the ReadonlyObject's properties are correctly exposed as readonly but I'm afraid it's bad practice.
I've seen implementations like this:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
Private _foo As String
Public Property Foo As String
Get
Return _foo
End Get
Friend Set(value As String)
_foo = value
End Set
End Property
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject.Foo = "bar"
End Sub
End Class
This works, but exposes the property with a setter. It's not accessible, but it's visible and I don't want that :)
So maybe it's only a cosmetic thing but I think it's nice to tell the caller (or at least intellisense) the property is strictly read-only.
Thanks, Jan
If you want to explicitly declare the property as read-only, but then still have a way to set it after it is constructed, then all you need to do is create your own setter method rather than using the one automatically created for you but the property. For instance:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
Private _foo As String
Public ReadOnly Property Foo As String
Get
Return _foo
End Get
End Property
Friend Sub SetFoo(value As String)
_foo = value
End Sub
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject.SetFoo("bar")
End Sub
End Class
Or, you could create two properties, like this:
Public Class ReadonlyObject
Protected Friend Sub New()
End Sub
Public ReadOnly Property Foo As String
Get
Return HiddenFoo
End Get
End Property
Friend Property HiddenFoo As String
End Class
Public Class FillReadonlyObject
Private Sub DoSomeHeavyWork()
Dim roObject As New ReadonlyObject
roObject.HiddenFoo = "bar"
End Sub
End Class

Handling Parent Property Event

Is it possible to listen to a parent class' object's event via the property accessor?
What I've tried (a minimal example):
Public Class ParentFoo
Private WithEvents m_bar As EventyObj
Public Property Bar() As EventyObj
Get
Return m_bar
End Get
Set(ByVal value As EventyObj)
m_bar = value
End Set
End Property
End Class
Public Class ChildFoo
Inherits ParentFoo
[...]
Public Sub Bar_OnShout() Handles Bar.Shout
' Some logic
End Sub
End Class
The specific error message I'm getting (VS2005) is "Handles clause requires a WithEvents variable defined in the containing type or one of its base types." Does accessing a private WithEvents variable via a public property strip away the 'WithEvents'?
In ParentFoo:
Public Overridable Sub OnShout() Handles m_bar.Shout
'No Logic Necessary
End Sub
In ChildFoo:
Public Overrides OnShout()
'Logic Here
End Sub
Since ParentFoo will call OnShout when m_bar raises a Shout Event and you override it in ChildFoo, your ChildFoo's OnShout will handle that event.

Hiding function on nested class

Public Class Class1
Private names As List(Of String)
Private _class2 As New Class2
Public Sub AddName(ByVal name As String)
names.Add(name)
_class2.Add()
End Sub
Public ReadOnly Property AddAge(ByVal name As String) As Class2
Get
_class2.index = names.IndexOf(name)
Return _class2
End Get
End Property
Public Sub Clear()
names.Clear()
_class2.Clear()
End Sub
Public Class Class2
Private _age As List(Of Integer)
Protected Friend index As Integer
Public Property Age() As Integer
Get
Return _age(index)
End Get
Set(ByVal value As Integer)
_age(index) = value
End Set
End Property
Public Sub Add()
_age.Add(0)
End Sub
Public Sub Clear()
_age.Clear()
End Sub
End Class
End Class
How can I hide ,Sub Clear and Sub Add on class2, so they'll only be visible on class1, like;
Public Sub Clear()
names.Clear()
_class2.Clear() '<<<<<<<
End Sub
I want they do not be visible on Sub Main(), like they are below.
Sub Main()
Dim person As New Class1
person.AddAge("kid").Clear() '<<<<<<
person.AddAge("kid").Add() '<<<<<<
End Sub
If I put Protected, I class1 cannot access it. If I put Protected Friend, Sub Main() can still access them. Thanks for your help and time.
Used -Hans Passant- comment.
"Trust in .NET follows assembly boundaries. If you get two classes in one assembly then there are two programmers that know how to find each other if there's a problem. The only way to get what you want is to put these classes in a separate class library project. Which then lets you use Friend. And whomever writes that Main method doesn't have to be friendly."

Dynamic ViewModelBase<TContext, TEntity> for CRUD operations using RIA

I am looking for an efficient way to create a dynamic CrudViewModelBase<TConext, TEntity> that will be used as a protortype for all the ViewModels in the application, that are going to perform CRUD operations.
I don't know where is the efficient way to instantiate the DomainContext, should be application-level? ViewModel-level? please share me with your experience.
I am pretty new to MVVM, and I want to create a reusable ViewModelBase to perform these operation.
Any links, code-samples, or recommendations will be really welcommed.
I start writing some stuff (I am new to RIA as well), I will be out for few hours sorry for delay in comments, and thanks for cooperating:
Imports System.ServiceModel.DomainServices.Client
Imports Microsoft.Practices.Prism.ViewModel
Imports Microsoft.Practices.Prism.Commands
Imports CompleteKitchens.Model
Namespace ViewModel
Public MustInherit Class CrudViewModel(Of TContext As DomainContext, TEntity As Entity)
Inherits notificationobject
Protected Sub New(context As DomainContext, query As EntityQuery(Of TEntity))
m_Context = context
m_Query = query
End Sub
Private ReadOnly m_Context As TContext
Protected ReadOnly Property Context() As TContext
Get
Return m_Context
End Get
End Property
Private ReadOnly m_Query As EntityQuery(Of TEntity)
Protected ReadOnly Property Query As EntityQuery(Of TEntity)
Get
Return m_Query
End Get
End Property
Private m_IsLoading As Boolean
Public Overridable Property IsLoading As Boolean
Get
Return m_IsLoading
End Get
Protected Set(value As Boolean)
m_IsLoading = value
RaisePropertyChanged(Function() IsLoading)
End Set
End Property
Private m_Items As IEnumerable(Of TEntity)
Public Property Items() As IEnumerable(Of TEntity)
Get
Return m_Items
End Get
Set(ByVal value As IEnumerable(Of TEntity))
m_Items = value
RaisePropertyChanged(Function() Items)
End Set
End Property
Private m_CanLoad As Func(Of Boolean)
Protected Overridable ReadOnly Property CanLoad As Func(Of Boolean)
Get
If m_CanLoad Is Nothing Then m_CanLoad = Function() True
Return m_CanLoad
End Get
End Property
Private m_LoadCommand As ICommand
Public ReadOnly Property LoadCommand() As ICommand
Get
If m_LoadCommand Is Nothing Then m_LoadCommand = New delegatecommand(AddressOf Load, CanLoad())
Return m_LoadCommand
End Get
End Property
Private Sub Load()
IsLoading = True
operation = Context.Load(Query, False)
End Sub
Private m_CanCancel As Func(Of Boolean) = Function() operation.CanCancel
Protected Overridable ReadOnly Property CanCancel As Func(Of Boolean)
Get
Return m_CanCancel
End Get
End Property
Private m_CancelCommand As ICommand
Public ReadOnly Property CancelCommand() As ICommand
Get
If m_CancelCommand Is Nothing Then m_CancelCommand = New DelegateCommand(AddressOf Cancel, CanCancel())
Return m_CancelCommand
End Get
End Property
Private Sub Cancel()
operation.Cancel()
End Sub
Private WithEvents operation As LoadOperation(Of TEntity)
Private Sub operation_Completed(sender As Object, e As EventArgs) Handles operation.Completed
If operation.IsComplete Then
Items = operation.AllEntities
ElseIf operation.IsCanceled Then
End If
End Sub
End Class
End Namespace
As giddy stated VM's and repositories are concerned with separate things. Just like with ASP.net MVC you wouldn't try and put that stuff in your controller. The ViewModel provides a model of the display and GUI things. Think of the ViewModel as the display. Take the view away and you should be able to test the functionality of the view by testing the ViewModel.
In my current project I'm making calls to my RIA domain services from the ViewModel and then mapping the results to my VM. If you want to use the repository pattern download the code from the silverlight firestarter event. http://channel9.msdn.com/Series/Silverlight-Firestarter/Silverlight-Firestarter-2010-Session-3-Building-Feature-Rich-Business-Apps-Today-with-RIA-Services session 3 Dan Wahlin, there is an example of this. The video is a good watch also.
This example by Shawn Wildermuth shows the client side model actually talks to RIA services. I haven't implemented it yet but it makes more sense to me as the model in his example feels more like a controller to me.
http://wildermuth.com/2010/04/16/Updated_RIA_Services_MVVM_Example
I personally don't like binding Data model entities directly to ViewModels. In my current project I don't have a choice because all access is done through procs so I map proc results to ViewModels. If I did have table access I would probably still map data model entities to ViewModels. I'm not sure that's "correct" in the mvvm pattern but it allows you to keep your data model entities clean of display/validation attributes.