DataBinding to reference types - vb.net

I've got some classes that have properties like this, and they work perfectly because they are very normal:
Public Overridable Property CustomerLastName() As String
Get
Return m_CustomerLastName.Value
End Get
Set(ByVal Value As String)
m_CustomerLastName.Value = Value
End Set
End Property
I want to change them to work like this (and don't worry about what IField is, suffice it to say it represents a field in a table):
Public Overridable Readonly Property CustomerLastName() As IField
Get
Return m_CustomerLastName
End Get
End Property
That way, you could do Customer.CustomerLastName.PreviousValue, or Customer.CustomerLastName.IsDirty, etc.
But that doesn't bind correctly. Understandable, since databinding is supposed to be a two-way thing, and there's reflection involved, etc.
Of course it can still be a two-way street, I just need to be able to say, "Hey DataBinding! Look over here!"
So. What do I do here?
Note: Right now, all I'm trying to do is DataBind to a GridView for display purposes. But I want this to be flexible.

(Update re edit) If it is just for display purposes, you can probably just set the ToString() on the class that implements IField.
(original)
No - 2-way data binding wants either INotifyPropertyChanged, or an CustomerLastNameChanged event. You can shim this into a custom model by implementing ICustomTypeDescriptor or TypeDescriptionProvider, but then you need to write your own PropertyDescriptor implementation.
Re IsDirty - that is ShouldSerializeValue in PropertyDescriptor terms.

Related

Why to use GET & SET methods while defining properties in VB.Net?

I am bit confused over the need to use GET & SET methods in VB.net. I want to discuss two cases in this connection: firstly when we declare the property as PUBLIC and next when we declare the property as PRIVATE.
What is I find is when I define a property as public I can directly set and access the values of that property without using the GET/SET methods --- quite simple: See below
Module Program
Sub Main()
Dim t As New test()
t.name = "Roy" 'Label 1
Console.WriteLine("t.name = {0}", t.name)
Console.ReadLine()
End Sub
End Module
Class test
Public Property name() As String
End Class
When I declare that same property as private, as shown below, I can still set and access the value of private property by simply using a constructor and a public subroutine. See below:
Module Program
Sub Main()
Dim t As New test()
t.printValue()
Console.ReadLine()
End Sub
End Module
Class test
Private Property Name() As String
Sub New()
Name = "Roy" 'Label 2
End Sub
Public Sub printValue()
Console.WriteLine("Value stored in NAME is: {0}", Name)
End Sub
End Class
So my question is why at all do we need to use the GET/SET methods? I understand that whenever an assignment happens to a property the SET method is implicitly called...but can you please help me understand cases where we MUST explicitly use the GET/SET methods? Or it is that using GET/SET is more of a choice? Validation is one thing that can be added easily at a later stage if one uses GET/SET but then is that the only reason? PLs give your views.
Also, I came across the following two related questions in stackoverflow (for different languages though): Links below:
Why to use getter and setter methods to set class properties?
Why use getters and setters/accessors?
But i could not understand most of the reasons justifying the usage of the GET/SET methods. For example if we dont use the GET/SET method then we are exposing the property to the outside world - meaning it can be directly accessed from outside the class. But then this is true only for PUBLIC properties as PRIVATE properties cannot be directly accessed from outside the class. Similarly in the second link the author mentions the following as a reason to use GET/SET: Providing a debugging interception point for when a property changes at runtime - debugging when and where a property changed to a particular value can be quite difficult without this in some languages. What exactly does this mean --- any simple real life example?
A property is a wrapper around a field, i.e., a class or struct variable. It provides a getter and/or a setter method to access this variable. (You can also have a read-only property returning the result of a simple evaluation not bound to a single field.)
The getters and setters are implicitly called when reading from, respectively writing to properties.
So, the question is not whether to use getters and setters or not, but whether to access fields directly or via a property.
You can declare a property like this, by declaring a field and writing the getter and setter explicitly.
Private _prop1 As String ' Backing field
Public Property Prop1() As String
Get
Return _prop1
End Get
Set(ByVal value As String)
_prop1 = value
End Set
End Property
or use an Auto-Implemented Property
Public Property Prop1 As String
Both declarations are equivalent. The auto-implemented property implicitly declares a backing field and implements the getter and the setter accordingly.
It can make sense to declare a property as private when you use it only inside the class where it is declared. This still provides the advantages described in the links you provided because this property still hides the details of accessing a field, does validations, etc.; however, it does not forbid the direct access to the backing field inside the class. So, you need to be more disciplined with private properties.
What does a property mean for debugging? You can easily set a breakpoint inside a getter or setter to detect accesses to a property. You cannot set a breakpoint on a field because a field is never executed. It is just a declaration.
You can also add a System.Diagnostics.Debug.Writeline("=====> test") (writes to the Output window) or do some logging in getters and setters.
See also: Tutorial: Learn to debug Visual Basic code using Visual Studio
When using Windows Forms Data Binding or WPF Data Binding properties are required. They also allow change notification.
Dynamically Calculated Values
I didn't read those links, but one reason you might want to implement your own getters & setters is that you may want to return something that requires some type of calculation or manipulation. For example, suppose you have item Sale with properties RawPrice, SalesTax, and FinalPrice. However, you need/choose to dynamically calculate the final price (based on variable sales tax) each time. So you first set the RawPrice, and then query FinalPrice, which returns RawPrice + SalesTax, but SalesTax gets dynamically calculated based on some other property like country of origin etc.
Alternate View of Data
Another reason you might want to do this is to provide another view of the same core data. For example, if your data was an HTML page, perhaps one property returns the normal string value, while another "no-HTML" Property has a custom Getter that performs some regex to remove all HTML tags and return a plain-text variation. This allows you to keep all related code inside of a sub-assembly, rather than having your main program do various manipulations.
Code Portability
This can make your life a lot easier down the road because of code portability. Your code is now more easily re-usable in other projects, since all you need is that one assembly.
Private Variables vs Properties
If I'm doing something that calls for a class with properties like that, there's good chances it's going to have methods, too. Those methods are almost always going to require creating private variables that nothing outside the assembly needs to know about. However, in such cases, they are not going to be private properties but rather simply private variables. For example, instead of Private Property Name() As String, with its implied auto-implemented backer variables with getters & setters, I would instead just say Private Name() As String, which would be equivalent to Dim Name() As String. You can use variables, constants etc. within your class just as you normally would, and, by default, the rest of the world won't know anything about them.
I'm not sure why you'd use a private Property. Maybe there's a good reason; I just don't know what it is. Most of the time, a private variable is probably what you really want. If you think there's a reason that you actually need a Private Property, I'm curious to hear your thinking on it. (I'm always open to a new way of thinking!)
History
Auto-implemented properties were not present in Visual Basic .NET for many years. In the past, you had no choice but to use GET/SET. So it's a more recent development for VB.NET to be able to simply declare a property as you do in your first code example, and for the runtime to automatically generate the backer variables.

Accessing an element of a custom type list by property value

Let's say I have a class called ControlInfo, which has the following properties:
Public Property Control As Control
Public Property ControlState As Int32
Now I want to create a method for accessing a specific instance of ControlInfo from a List, so I do this:
Public Function GetInstance(control As Control) As ControlInfo
For Each c As ControlInfo In list
If c.Control.Name = control.Name Then
Return c
End If
Next
Return Nothing
End Function
Is there a better way to access specific instance from a list of a custom class based on its property value? Is the loop approach bad for performance?
Sidenote: I have also considered the implementation of a Dictionary other than a List (so I would access an instance via a key, which can be a lot better than looping through all the values), but I feel that if I resort to that I would be avoiding a problem instead of solving it. Maybe I am being paranoid but I would like to know other valid approaches here, and be more certain of what should/shouldn't be done.
Thanks.

Advantages of Properties in Classes

I've been using classes for a while now, but I feel I may have been using them incorrectly.
When I create the properties for the class, I just use public variables so I end up with something like the following:
Class clsMyClass
Public Name As String
End Class
However, I've been reading some info on the net and they suggest that it should be set up in the following way:
Class clsMyClass
Private Name As String
Property UsersName() As String
Get
Return Name
End Get
Set(ByVal Value As String)
Name = Value
End Set
End Property
End Class
Is the way I'm doing it extremely incorrect? If so, why? I feel like the second method adds some sort of security but to be honest, it just looks like unnecessary code..?
One advantage of properties is that they let you customise the access to your private fields and enable you to do more so you can do the following (examples, it's not limited to that):
Make a property read-only for public access
Raise an even when a property is updated
Update other private fields when a property is updated
Validate the value that is being set
See below advantages of Properties over Variables from the C# in Depth article:
• There's more fine-grained access control with properties. Need it to be publicly gettable but really only want it set with protected access? No problem (from C# 2 onwards, at least).
• Want to break into the debugger whenever the value changes? Just add a breakpoint in the setter.
• Want to log all access? Just add logging to the getter.
• Properties are used for data binding; fields aren't.
Few other points:
1) You can also make properties read-only so no one from outside the class set the values but can fetch it.
2) You can do certain actions in the get and set. i.e. Append a prefix anytime set is called
3) You can also use auto-implemented property to minimize code like below:
Public Property Name As String
You are not doing anything wrong. Properties give you a shorthand basically, a syntactic sugar.
You can still use a backing private variable and do logic in get and set if you have to while using properties. Even better is the private/protected set or get, which is again another syntactic sugar so that you won't have to write all the code manually.
First of all, VB.NET allows you to use this syntax (called shorthand property declaration - I believe since VS 2010):
Public Property Name As String
Not so much different from this (called field declaration):
Public Name As String
Second, Microsoft data binding does not work well with fields. Try this example (see below).
Example. Put a listbox called ListBox1 (default name) and a button called Button1 on an empty form in an empty WinForms project. Replace your form code with this:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst As New List(Of clsMyClass)
lst.Add(New clsMyClass)
ListBox1.ValueMember = "Name"
ListBox1.DisplayMember = "Name"
ListBox1.DataSource = lst
End Sub
End Class
Class clsMyClass
Public Property Name As String = "Hello"
End Class
Start the application and notice that a listbox is populated with one entry, Hello. This proves that binding worked correctly. Now replace your property declaration with a field declaration instead. Start your application one more time and notice that a listbox is showing your class type converted to String. It means that your field binding did not work, and default binding was used instead, where DisplayMember is assigned sort of classInstance.ToString().
If you are curious to learn more about what happens behind the scenes, you can put a breakpoint on .DataSource assignment, and see how DisplayMember gets reset or keeps its value depending on whether you are using fields or properties.

Changing source collection of ObservableCollection property

One of my library classes exposes a property that looks somewhat like this:
Private _myCollection As New ObservableCollection(Of String)
Public ReadOnly Property MyCollection As ObservableCollection(Of String)
Get
Return _myCollection
End Get
End Property
I don't know too much about databinding, but I'm assuming that the framework will automatically notify about changes when items are added to / removed from the underlying _myCollection field (correct me if I'm wrong).
What I'd like to know is what happens when _myCollection is nulled or replaced with a different collection:
Sub WhatHappensToMyObservableCollectionWhen(updated As Collection(Of String))
' nulling underlying field
_myCollection = Nothing
' changing underlying field
_myCollection = New ObservableCollection(Of String)(updated)
End Sub
Will the framework still notify that MyCollection has changed, or do I have to implement INotifyPropertyChanged and raise PropertyChanged manually when these things occur?
EDIT
I'm asking this question with WPF developers in mind, but I guess the answer will be the same for all observers of PropertyChanged. If a GUI written in WPF binds to MyCollection, I want to make sure that it is properly updated when the _myCollection field changes in the ways that I have described.
Thanks

Should I create individual properties in a class or just a method to set the values?

I am learning vb.net and I am having trouble wrapping my head around the following...
I can create several properties of a custom class and get/set values or I can create a method to set them all at once. If each property is going to allow read and write should I just make a method to assign values all at once? I assume that I am missing a very important piece here. Example:
I can create 2 properties:
Public Class Employee
Public Property LastName as string
Get
Return strLastName
End get
Set(ByVal value as string)
strLastName= value
End Set
End Property
Public Property FirstName as string
Get
Return strFirstName
End get
Set(ByVal value as string)
strFirstName= value
End Set
End Property
End Class
or I can create a method:
Public Class Employee
Public Sub AddEmployee(ByVal strLastName, ByVal strFirstName)
LastName = strLastName
FirstName = strFirstName
End Sub
End Class
I apologize for such a noob question, but any insight is greatly appreciated. thank you!
If you only have a single method, you will have to use it even if you only want to change the value of a single field.
Additionally, in such a method, if you need to validate the input, you will need to write quite a lot of code for validation that is not relevant to all of the fields.
If values must be updated together, use a method to update them together and do not provide setters.
The reality of things is that how to do this depends on what you are modelling in your class. There are no hard and fast rules that say that properties are better than methods or vice versa.
There is no reason not to support both properties and a method that sets multiple properties.
Commonly, a constructor is used to create an instance of the class and to set some properties. In VB, naming a class method "New" defines it as a constructor. In your example, if you rename your AddEmployeee method to New, you will have a perfectly fine constructor. Then you program can create new instances as such:
Dim emp1 as New Employee("Burdell", "George")