I am making a personal WinForms app. In my scenario say I have a C# Form1. Form1 is constantly getting live Exchange data from the Internet. Now I click a button on Form1 and Form2 opens. Now I want some values from Form1 on Form2.
I have a timer on Form2 which can collect data from Form1 but how?
I had tried to use properties but not able to do that as it updates only once as when we initialize Form2.
Any solution?
Also, how can I pass a single instance of a class to both forms, if they are not being created at the same time?
I. Solution: Use a Common Data Source
Method 1: Data Source with Events
Well, if it were me, I would probably not be trying to directly get the data from Form1. Instead, I would set up a common datasource, and then you would even be able to eliminate the timer on Form2 and drive it by when the data comes in if you like. (Or you can leave it and just pull from the datasource as your desired intervals.)
It would be something like this:
Data Source class
Then, when you are opening your forms, you’ll just create an instance of ExchangeCommonDataSource, and pass it to both of the forms. In the form that is receiving the data you’ll want to create an event handler function, and wherever you pass it the data source, you’ll hook up that event.
example: receiving class code
Then, in your first form, you just set the properties you want. You can actually have notifications that specified the actual data to load, either through separate event handlers, or by creating your own derived EventArgs and then using
EventHandler<ExchangeCommonEventArgs>instead of a regular event handler.example: main form data accessor
Also, this way you’re not limited to having just those two forms communicate; if you decide to split it up with different forms, you could have each of them have a copy of the data source and each of them could handle the event or new events you define, and you’re not tied to a model where you’re expecting to communicate directly between each other. This would also allow, for instance, creating a separate class which writes some log data to disk, or whatever else you can imagine, without making significant changes to any of your existing stuff.
II. Extensibility for External Updates
The Dispatcher Base Class
So, what if you want to update to eventually send to another application or another machine even?
Well, this is actually very well accounted for since you’ve not got any dependencies on the forms left. So, say you wanted to support three methods: the initial, form to form method; sending via a named pipe to another app on the same machine; and TCP/IP to another machine entirely. All you would need to do is to define a class that acts as a dispatcher, hook it up as a receiver, and then you can hook up that object to take the events coming from the form and put the data wherever you want.
It should be fairly straightforward to define an abstract class or interface to do this, and then simply derive a class for any mode you want to support:
example: a notional abstract Dispatcher class
see the Microsoft page on IDisposable for some great example code and more information on IDisposable…
Deriving Dispatchers for Other Communication Methods
There’s no way to make the form itself derive from this class, but there’s no real need since you can just hook up as before. But, as quick example (just notional, not actually implementing the protocols, and you really should really consider the best way to implement these types of things, but I wanted to give you a fairly comprehensive example of what it takes, it’s not as simple as the really really naive versions tend to be. )
example: (very) notional Pipe-based Dispatcher
Phew. Note that I’m very unhappy currently with the length of the
StartPipeThreadfunction, and I would definitely be refactoring that.So, you could also implement this for TCP/IP sockets, or whatever protocol you can imagine, and it’s all handled without having to continually modify the classes from the first section.
My apologies for the quality of any of the code there; I am open to suggestion/correction/flaming about it, and I’ll do my best to make corrections if you just let me know. 😛
III. Putting the Data Where it’s Needed
After you have this set up, you’ll need to pass the same data to whatever forms are using it. If you’re not creating both your forms at the same time, then you’ll need some way to get each destination a reference to the same data source. (Note: the numbering of the options is in no way intended to imply these are your only choices!)
Here are a few options for doing so:
Option 1: via Property on your main Form
This method is appropriate if your main form is responsible for creating each of the child forms, for instance, through menu items. You simply create a member variable to hold the data, and wherever you create the data, store a reference to it in that member. If you have multiple instances of the source, you can store them e.g. in a dictionary that allows you to look up the one you need.
example: code for main Form
Option II:
staticProperties on your Data SourceThis option can be used if the forms are being created externally from the main form, in which case you will not have access to its methods. The idea behind this method is that you want an easy way to find whatever item you need, independent of the main form itself, and by providing a static method, additional data consumers can find the sources on their own using properties accessible with access only to the class declaration and then some sort of key if there can be multiple sources.
example: ExchangeCommonDataSource.cs
now to access, the client just needs to have some sort of key to access the data:
example: frmClientClass.cs
I find this a generally more compelling solution that Option 1, simply because anything that has access to the class and an ID can get the data source, and because it’s fairly easy to implement, and it gives automatic support for doing multiple instances of your data source class.
It has fairly low overhead, and since getting a data source is, in most cases, something that is not going to be done in tight loops (and if it were, you would have local copies, not looking them up from a dictionary every time) any small performance loss should be worth the ease of use. And, best of all, even if you start with one data source, you can easily extend your application to more without having to rewrite any code or go to any further effort.
For instance, a very quick way to use this assuming you only have one data source would be just to use a known value for your Dictionary key, and then you just can hard code that in your second for for now. So, for the example, you could just have the empty GUID as your key, and use that for both your forms. i.e. the Main Form or your first data form would call the create method with Guid.Empty to create the data initially, and then you can just use that to access it when the time comes to open your second form.
Option 3: The ‘Singleton’ Pattern Class
Okay, I’m not going to spend much time or write code for this one, but I would be remiss if I didn’t mention it. It’s very similar to option 2, except, instead of having a static Dictionary to look up multiple data sources, you create a class that has one instance of the class stored in a static property, and you prevent (via exception) any attempts to create more classes. Then, you set all constructors to
private, have them throw exceptions if the static variable already contains an object, and you create a getInstance() method which returns the single instance of the class, creating it if it’s null.Now, there are some little thread-safety trickiness issues with this that you will need to understand to write a traditional singleton, so be sure to understand those (there are questions on StackOverflow dealing with the issue). If you don’t need any particular knowledge to construct the instance of the class, you can avoid the issues by simply initializing the variable where you declare it e.g.
static MyClass theInstance = new MyClass();, and I highly recommend doing that if you do ever use one.I have used Singletons in the (fairly distant) past, and it’s not that they don’t occasionally have their uses, especially in embedded systems. But, this is not an embedded system, and almost every time I used a Singleton in a GUI application, I regretted doing it because I ended up eventually re-writing it into something that would allow multiple instances. If you really just need one copy, all you have to do is put a member variable in the class that uses it, say, your main form, and make sure that you don’t ever create but one. Doing this, you could even use the pattern by setting a static flag in the class that you can trigger an exception on; set it to true when you first create the object, and then if that’s true you can throw your exception.
Anyway, my personal first rule for when to write a singleton is: don’t do it unless you are certain you will never need more than one. If it passes that one, then the second rule is: you are wrong, there is a way it could happen, so just write it as a normal class and handle the singleton-ness of it in some other way. 🙂 Seriously though, the real rule is, just don’t do it unless you have get some a very solid reason or a significant benefit from doing it.
Oh, and to reiterate: it’s very possible to accomplish the pattern of singleton, without writing the canonical singleton class. The pattern is fine, just do it in a way that when that need for a second instance of that class comes along, there is a very low cost to eliminate the pattern.
Option 4: A Separate Class
Option 4 is very similar to Option 2, but implemented in a second class. (In fact, if you ever think you might have multiple sources of data, it would be worthwhile to just start here, although it’s a little more time to set up initially.) Instead of having your static items as members of that class, implement another class that has something like them and provides access. This is a way to decouple the class itself from the creating of it. For example, if you were writing a library, and you wanted to provide several different types of data source, you could implement a base class and then derive your other objects from the base class, and then provide creation mechanisms via a class that gives factory methods to create the different kinds.
In a situation like this you very well may not even want whatever is using your data source to have to know anything about the implementation of the data source classes at all, and only go through the base interface, and this provides an easy way to do that. If you had to write it all as base class static members, then you would be forcing a rewrite of the base every time you derived a new class, and it would also be forcing the base to know something about the derived classes, each of which is, in general, something to avoid. In other words, it’s not that it’s never useful, but don’t do it without very good reason, and don’t do it without understanding the implications.
example: code for external class
InfostoreBase.cs
InfostoreEnterprise.cs
InfostoreHomeEdition.cs
InfostoreProvider.cs
code in client class
Closing
I think that covers a very good range of possible solutions; none of them is particularly hard to implement, and each has its own benefits and disadvantages. In general I would go for Option 2 or Option 4, but [broken record] it always depends on your exact situation. I think it would be fairly easy to use extend these to handle lots of different situations. And of course if there are any problems, just let me know.