Suppose I have 3 classes to handle all database related requests:
public class DB_A{}
public class DB_B{}
public class DB_C{}
and I got 2 windows to interact with user:
window1.xaml;window1.xaml.cs;
window2.xaml;window2.xaml.cs
as window1 & window2 need to interact with database, they need to use functions from previous 3 classes, I created a class DataHandler:
public class DataHandler
{
public DB_A a;
public DB_B b;
public DB_C c;
public DataHandler()
{
a = new DB_A();
b = new DB_B();
c = new DB_C();
}
//some functions... ...
}
now the class DataHandler can handle all database related request, and now i need to pass a instant of DataHandler to both window1 and window2.
I tried to re-write the constructor for both window1 and window2 with parameter, but it does not allow me to do that. After google i know that WPF window form does not allow constructor with parameter.
Is there any way to pass my DataHandler to the two window form classes?
Make DataHandler a singleton, and let the window classes access it.
public class DataHandler
{
//singleton instance
static DataHandler _instance = new DataHandler ();
public DataHandler Instance
{
get { return _instance; }
}
};
Then,
public partial class Window1 : Window
{
DataHandler _dataHandler;
public Window1()
{
InitializeComponent();
_dataHandler = DataHandler.Instance;
}
}
Similarly, write other Window class.
Or even better is, apply some variant of MVP pattern, most likely, MVVM. Read these articles:
Composite Guidance for WPF : MVVM vs MVP
WPF patterns : MVC, MVP or MVVM or…?
Model-View-Presenter Pattern
Model View Presenter
Yes, you can, there are multiple ways to do that,
you make your DataHandler a singleton. ( I do not like this one)
add a public static property to app.xaml.cs that has an instance of your DataHandler class and in your Windows’ constructor take that from app. (it’s a better approach)
add a ViewModel and let that view model present data to both Windows. (I prefer this one!)
If you need an example let me know which one works for you and I will provide one.
Can't you make the DataHandler class to singleton and use it's methods on wherever you want, without re-instantiating the class?
You can have parameters on your Window constructor. Alternatively you could pass it in through a property, set your DataHandler object to a public static property somewhere, or even just make your DataHandler a static class.
There are any number of ways to accomplish this.
You can make DataHandler a singleton.
Since DataHandler has a parameterless constructor, you can create it in the application's resource dictionary, and let objects use FindResource to get it.
One pattern that you'll see pretty commonly, in implementations using the MVVM pattern, is that the view models contain a reference to shared objects, and windows get access to them through binding, though I doubt very much that you're using MVVM.
Related
I'm making a media player program and I have the following interface:
public interface IMediaService
{
void Play();
}
Would it be more appropriate to inherit the interface in the view where the MediaElement control resides and access it directly in the implementation of the methods or rather have it in a separate class like this:
public class MediaPlayer : IMediaService
{
private MediaElement _mediaElement;
public MediaPlayer(MediaElement mediaElement)
{
_mediaElement = mediaElement;
}
public void Play()
{
_mediaElement.Play();
//...
}
}
vs inheriting it in the view:
public partial class MainWindow : IMediaService
{
public MainWindow()
{
InitializeComponent();
}
void IMediaService.Play()
{
Player.Play();
//..
}
}
I'm not using MVVM, but those methods might be used as bindings through commands.
The problem I see in the second approach is that my view class will get cluttered really fast.
I'm open to any alternative solutions that I haven't mentioned, this is just what I've come up with atm.
Would it be more appropriate to inherit the interface in the view where the MediaElement control resides and access it directly in the implementation of the methods or rather have it in a separate class like this:
It doesn't really matter as far as MVVM is concerned. There is no right or wrong really. It's depends on the developer's personal preference. If you don't want to pollute your view, you create a separate class. If you don't mind adding some methods to your view, you don't.
The benefit of using a seperate class is that you may reuse it for several different views/MediaElement.
But the view model only cares about the interface itself, i.e. it has no dependency upon the actual implementation of it.
I have a fairly simple application that monitors folder activity and logs it on a server.
In this application I start off with a Form object called Form1. On this form I have a NotifyIcon. Because I need to change the text in the BalloonTip of the NotifyIcon from different Forms along the way, I was thinking of setting a static property of Form1 that will point to the only instance of Form1. This is how it would look in my oppinion:
public partial class Form1 : Form
{
private static Form1 staticRef;
// Other private properties
public Form1()
{
InitializeComponent();
staticRef = this;
// Rest of constructor logic
}
public static void changeNotifyBalloonText(String newText, int timeInMillis)
{
if (staticRef != null && staticRef.notifyIcon1 != null)
{
staticRef.notifyIcon1.BalloonTipText = newText;
staticRef.notifyIcon1.ShowBalloonTip(timeInMillis);
}
}
// Rest of public and private methods
}
Other things to be noted:
a. There will never be more than 1 instance of Form1.
b. I always check the value of staticRef against null, before trying to use it.
c. I cannot afford to make a temporary, local instance of Form1 just to set a BalloonTip message.
d. This solution works very well, i'm more interested in knowing if it's "too hacky" and if so - what would be a better approach to my issue?
e. The closest thing I've found that may answer my question (about static properties) to some degree is here:
Is using a static property in a form bad practice knowing that there's only only one instance of the form?
What you have here is a form of the singleton pattern.
The singleton pattern certainly has its detractors and its defenders (google "singleton anti-pattern").
It is though a very convenient way of doing this.
I would recommend an approach like either::
Create a class that represents operations on a notify icon.
Have that class as the only class that accesses staticRef.notifyIcon1.
Have it do so as a reference to notifyIcon1, not as Form1.
Have a static method or property that gets the icon-controlling class.
Or:
Simply have a static method or property that returns the NotifyIcon object.
Make it the only method that accesses the static reference to the form.
The advantage of one over the other is around whether you want to expose the full interface of NotifyIcon or provide a set of operations that make sense to your application.
This way you are still using the singleton pattern, but in restricting the way that it is accessed the fact that there is global state has less of a global impact, relates more directly to the purpose of that global state (the icon itself), and is more readily extended to different uses. e.g. if you some day need to have two icons, you change the method that static method or property to one that does a lookup of some sort, and change all the current calls to use the key for the first icon. Meanwhile, implementation changes up to and including completely changing which form provides that icon can be done quickly in one place.
I think your current design is tightly coupled to other classes sending the notification and it requires your form to be a single instance as well.
You can decouple this a great deal by using an event broker to send the notification to any interested parties. Many frameworks have event brokers, I have used one from Prism but there are others as well.
Your code will then only know about the event broker and what events your class is interested in.
public partial class Form1 : Form
{
private static IEventBroker eventBroker;
// Other private properties
public Form1(IEventBroker eventBroker)
{
InitializeComponent();
this.eventBroker = eventBroker;
this.eventBroker.Register<NotifyBaloonText>(changeNotifyBalloonText);
}
public static void changeNotifyBalloonText(NotifyBaloonText args)
{
notifyIcon1.BalloonTipText = args.NewText;
notifyIcon1.ShowBalloonTip(args.TimeInMillis);
}
// Rest of public and private methods
}
I have a MainViewModel, which features PersonViewModel and a HouseViewModel as properties. HouseViewModel has the property GetRooms. What is the best way to access this property from the PersonViewModel?
My solution at the minute is to pass through an instance of MainViewModel to PersonViewModel, then I can call MainViewModel.HouseViewModel.GetRooms. However, this seems a little wasteful.
I am happy to pass a function as a delegate, but I can't seem to do this with a Property. I have searched for an example of this and only come up with overly complicated techniques. I'm assuming there must be a simple way of doing this, as it seems like a common problem. Can anyone point out a strong example?
Or is there another, alternative method that I haven't considered?
If a method has to be shared across two viewmodel, it should be defined in base viewmodel or a service. The best way is a common Service class should hold all common methods like GetRooms, CheckIn, CheckOut, etc. And this service should be provided to every viewmodel using Dependency Injection.
public class HomeViewModel
{
public HomeViewModel(IRoomService roomservice)
{
}
}
public class PersonViewModel
{
public PersonViewModel(IRoomService roomservice)
{
}
}
Hey guys my issue is that i can't use the common class class1 = new class(); and just do class1.method1(); because if I make a new instance of the class it would open a new form and the class also has a constructor. I just need that one method from the class nothing more.
To use a class' instance method, you need an instance of that class; no exceptions*. If its constructor opens a form, make it so that it doesn't.
You may need to re-consider your design pattern as if this class1 you speak of is a Form then stopping the UI from showing in such a manner is not a particularly proper design pattern. Update your question with your current implementation so people can better advise you!
If you are manually instaniating and displaying a Form from within the class1 constructor you could consider an implementation like this:
public Class1(bool showForm)
{
if (showForm)
{
//Show UI
}
}
If you must you could hide the UI like so:
protected override void SetVisibleCore(bool value)
{
base.SetVisibleCore(false);
}
I have a WinForms project, which uses a lot of user controls. Some of these user controls use classes from business logic layer. These classes are mainly performing CRUD operation to a database (through data access layer) plus some additional validation and reporting.
The project uses some common objects (logged user, some controllers and validators), which are instantiated in main form and then injected into child user controls via initialization methods or public properties. This means, that I have a lot of code, which just passes these common objects from parent control to child controls.
In order to avoid this, I could create a static class (ApplicationContext for example) and save all common controls into it. This would happen in the main form and all other user controls or forms in the project could use it.
I see that this pattern is discouraged in general (storing some global data in static classes). But what if this data is immutable? Is this approach ever a good idea?
Or do you know any other approach, which could help me get rid of all the initialization code?
You can use an Inversion of Control container like Unity or Autofac and have it automatically wire up your object graph for you.
You can have each object that requires any one of the common objects define a dependency to their interfaces, either though a constructor argument, or as a public property, and the IoC container will wire the appropriate objects together.
Property injection example with Unity:
public class MyUserControl : UserControl
{
[Dependency]
public LoggedUserService UserService { get; set; }
public void Method()
{
// the IoC container will ensure that the UserService
// property has been set to an object
}
}
All you do in the main form is registering the common objects you want the IoC container to know about and then you ask for the root object. The object graph will be assembled magically for you and you don't have to to all the wire code nor care how it is done.
You can use a dependency injection / ioc container for maintaining your global objects.
I have made good experience with the autofac library but there are many other available.
When using setter injection, all of your controls get set dependent objects set automatically.
You'll want to use Singletons for this situation. Singletons will allow you to use the same instance of your object, more safe and flexible than static.
public sealed class Singleton
{
public object Property1 {get;set;}
public void Method1 (){}
static Singleton instance = null;
static readonly object padlock = new object();
Singleton()
{
}
public static Singleton Instance
{
get
{
lock (padlock)
{
if (instance==null)
{
instance = new Singleton();
}
return instance;
}
}
}
}
then you can use it like you would static, but a bit different...
public class Main
{
public Main()
{
Singleton.Instance.Property1 = "somevalue";
Singleton.Instance.Method1();
}
}
You can use a static class to store some immutable data - no problem with this.
How ever if you want to store controls there it might not work as expected.
For example method like OnDataBinding and Render.