referencing class in multiple forms

NachitoMax 411 Reputation points
2021-04-15T19:25:57.25+00:00

Hi

thought it would be easy enough, maybe im missing something logically...

As i select a product, i load that specific product form. in the form, a reference a class instance (Info) that has already been instantiated on startup in ApplicationEvents-

Dim Inf As New Info

as i load my product form, i have set it like that to access the class without creating a new instance of it

Private _Inf as Info

In my New class, i do this

_Inf = My.Application.Inf

this seems to work but i dont think its the best method. however, when i do the exact same in a sub UserControl on the product form, i get an exception error on a control EditEvent. I understand that this is because the _Inf has completely been qualified yet as the form isnt 100% instantiated.

So

what is a good method for multiple forms to access the same class containing data?

i could use My.Application.Inf for all access but is there a better way?

Thanks

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,264 questions
0 comments No comments
{count} votes

7 answers

Sort by: Most helpful
  1. NachitoMax 411 Reputation points
    2021-04-15T19:45:58.853+00:00

    in addition, i did try it as a shared member of ApplicationEvents

    Public Shared Inf As New Info
    

    but couldnt access it using the above methods or a direct call

    My.Application.Inf.Something
    
    0 comments No comments

  2. NachitoMax 411 Reputation points
    2021-04-15T19:58:00.143+00:00

    well, i created a new Class called AppGlobals and added the instance in there like this

    Public Class AppGlobals
      Friend Shared Inf As New Info
       ' add others here required
    End Class
    

    which works by typing

    AppGlobal.Inf.Something
    

    in any class without needing to create an instance of it. Is this methods acceptable or is there a correct way that im not doing?

    Thanks

    0 comments No comments

  3. Michael Taylor 45,996 Reputation points
    2021-04-15T20:13:30.49+00:00

    In general you're asking to use global variables and that is almost always the wrong approach. The only time, I believe, global variables are appropriate is when you are going to store something that is immutable for the life of the application. Examples might include the product information or a cached copy of a lookup table loaded from the database. In all other cases I don't believe global variables are a good idea. They should almost never be mutable as this can cause problems if they are updated while someone is trying to use them (especially for lists of items).

    Nevertheless in the cases where global variables make sense I prefer to create a standalone shared class that exposes the data. The data is generally loaded upon first use (using Lazy when possible) and then remains unchanged for the life of the application. Following the single responsibility principle I tend to use a separate shared class for unrelated data but single shared class for related data. Going back to the product information, this is probably in a class by itself simply because nothing else makes sense.

    Note: My VB is rusty so expect issues.

       Public Class ApplicationInfo  
          ' Singleton stuff, globally shared data  
          Public Property Shared Default() As ApplicationInfo  
             Get   
                Return _application  
             End Get  
          End Property  
         
          Private Shared _default As New ApplicationInfo  
         
          ' Instance data  
          Public Property Name As String  
             Get  
                  'Do work to get name of application  
             End Get  
          End Property  
       End Class  
    

    In this example I'm using the singleton pattern. I prefer a singleton object over a shared class because it gives me flexibility to move away from singleton later without having to update a lot of code. The net effect is the same though.

    To use it.

       Sub Foo  
           Dim appName = ApplicationInfo.Default.Name   
       End Sub  
    

    In the case of commonly needed data then I prefer to use methods on a shared class that can then cache the data if desired.

       Public Shared Class GeographicService  
          Public Shared Function GetCountries () As IEnumerable(Of Country)  
              ' Get country data from DB if not cached  
          End Function  
         
          Public Shared Function GetStates ( ) As IEnumerable(Of State)  
             ' Get states from DB if not cached  
          End Function  
       End Class  
    

    Usage.

       Sub Foo  
           Dim countries = GeographicService.GetCountries  
       End Sub  
    

    But I generally recommend you not going this route just to share data between forms. In most cases expose properties on the form(s) (or create a constructor that has parameters) and allow the caller to provide the data (even if across forms). Ideally you are using some sort of servicing layer that exposes services that you can pass to your forms.

    0 comments No comments

  4. NachitoMax 411 Reputation points
    2021-04-15T21:02:49.967+00:00

    Hi

    Thanks for the detailed reply. I originally had the variable members in my specific Product form because nothing except the form itself and its sub forms required access. I was passing the data down to the sub forms using a Constructor with parameters but was advised that the method should be avoided and instead, Delegate from the sub form to the parent form which is what i have done now.

    The data is updatable but locally per user. Each sub form requires access to get / set the data and the parent form requires access to update a model. It is then processed from the parent model as a complete data set. So, there are different datasets per different products and i only need to load the specific product elements required.

    In this image, i try to demonstrate what im thinking which is-

    • Create the ProductForm on demand by Product
    • Create the Subforms required for the ProductForm
    • Create the Data Class specific to the product
    • Subforms Get / Set data as required through UI to / from DataClass
    • Invoke an update on the ProductForm to graphically display the DataClass Update
    • Process the data in a final method to its destination
    • Dispose of the Product Form and all of the objects created for the product

    88346-object.png

    Apologies for incorrect naming here, this was done for a non code team meeting..

    It looks like i need to instantiate the DataClass either as the productForm is loaded or Directly after on the ProductFormCreate method then Dispose of it after while not creating a direct link between the form & subforms..

    Hope that make sense :S

    0 comments No comments

  5. Michael Taylor 45,996 Reputation points
    2021-04-15T21:10:30.79+00:00

    I'm not sure what the original conversation was around why you should avoid constructor parameters as this is the correct approach in most cases. There is a fine line between required and optional data however. If the data is required then a constructor parameter ensures the compiler will prevent someone from opening the form without a product (of course it could still be Nothing). However if it is optional then a property is the better route. In either case the data should be passed from the parent to the child form. This eliminates the need for any additional support types.

    Furthermore it would allow you, in the future if desired, to support opening multiple product forms at the same time with each of their sub forms and there would be no chance that any confusion would occur.

    I do agree that the product form (parent) should be responsible for getting the initial data and probably saving that data but I could also see each sub form loading and saving its portion of the data. But none of this is really related to getting the data into the form to begin with. Using a shared data class to avoid a constructor parameter or property assignment is introducing unneeded complexity to a simple problem. There may be other business reasons that I'm not aware of though.

    ' Required data is passed as parameters
    Dim child as New ChildForm(product)
    
    ' Optional data can be set on properties
    child.OptionalStuff = optionalData