2

Suppose I have two Pages in WPF namely Page1.xaml and Page2.xaml. I have one viewmodel named PageViewModel.cs. Both of those pages share the same viewmodel.

I can write my code by two methods:

Mehod1:

PageViewModel.cs

public static class PageViewModel
{

}

Page1.xaml

<Window.........>
    <Window.DataContext>
        <vm:PageViewModel />
    </Window.DataContext>
</Window>

Page2.xaml

<Window.........>
    <Window.DataContext>
        <vm:PageViewModel />
    </Window.DataContext>
</Window>

App.xaml

Default xaml code.

Method2:

PageViewModel.cs

public class PageViewModel
{

}

Page1.xaml

<Window DataContext={StaticResource PageViewModel}>
    ..........
    ..........
</Window>

Page2.xaml

<Window DataContext={StaticResource PageViewModel}>
    ..........
    ..........
</Window>

App.xaml

<vm:PageViewModel x:Key="PageViewModel" />

Can anybody explain the difference between above mentioned two methods?

Vishal
  • 6,238
  • 10
  • 82
  • 158
  • 3
    why not look up the documentation or read up on the difference on MSDN http://msdn.microsoft.com/en-us/library/aa645766(v=vs.71).aspx – MethodMan Aug 25 '14 at 19:48
  • 1
    I have read the documentation, as well as I have watched some videos on Static and Instance members. Still I don't get the exact difference and when to use one over the other. So I asked it on this site. – Vishal Aug 25 '14 at 19:51
  • Scope. Limit your classes to as small a scope as you can. By making the class `static`, you're effectively making it a global variable. By limiting your scope, you can always be sure which part of the application is accessing a given object at a given time. – crthompson Aug 25 '14 at 19:58

2 Answers2

6

The primary difference will be that in your first example, any object or method can access your view model, its data, and its methods.

In the second, you have an actual instance (albeit contained in a globally accessible object), so while other objects could still get to it, its not as easy as "access the static (read, global) instance".

Both have the same effect, you get data shared between the two views.

One additional option you may want to consider would be to pass the view model in on the constructor of the view. You have to use the code-behind, but you can give both view's a reference to the same view model object without having any global variables.

If these are subviews, then you could do the following:

MainView.xaml.cs

public void MainView()
{
     SubViewModel subVm = new SubViewModel();

     //If you are instantiating your views
     MySubView view1 = new MySubView(subVm);
     MySecondSubView view2 = new MySecondSubView(view2);

     //Otherwise
     view1.DataContext = subVm;
     view2.DataContext = subVm;
}

In the spirit of the locator pattern, you could also simply bind the DataContext property of the sub views to a SubViewModel property on your main View Model.

The one thing to be aware of with this is that the View Model's lifetime will end once both sub views are destroyed. If you need a longer lifetime, then you should use the latter option and point it towards a long-lived object.

In general, I would stay away from static classes. They make unit testing, and good design in general, much more difficult to achieve. If you need a singleton, at least implement one properly as opposed to just using a static class.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • Can you explain me last second paragraph with an example? – Vishal Aug 26 '14 at 01:29
  • @Vishal I tried to clarify and added an example. Please let me know if I can provide more information. – BradleyDotNET Aug 26 '14 at 05:12
  • I have accepted this as an answer but I really don't understand the code provided by you as I don't know the concept of Sub-Views. Can you point me to any good tutorial? – Vishal Aug 26 '14 at 07:33
  • @Vishal Perhaps I should have said "Nested View". I'm assuming you have one "Master" view and all these other control are children. Even if they aren't, you can still apply the same concepts. Its not a new concept, just an extension of one you already know, so I'm not sure I could recommend a tutorial. – BradleyDotNET Aug 26 '14 at 15:03
  • Thanks for the explaination. – Vishal Aug 26 '14 at 15:33
  • I am somewhat confused but i can't chat with you right now because i don't have computer with me right now. I have sent this comment from my mobile phone. – Vishal Aug 26 '14 at 16:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60027/discussion-between-bradleydotnet-and-vishal). – BradleyDotNET Aug 26 '14 at 16:39
5

This won't answer your question, BradleyDotNET has done that, but I just can't help my self here.

This is a perfect example for using a ViewModelLocator, try to install a framework such as GalaSoft MVVM Light. You may use your Locator to keep track of your viewmodels, static viewmodels are bad pie(you are going to run into alot of problems you can avoid).

I can't see where you have declared your static resource, but I assume it is in App.xaml ?

Check this post for using a viewmodel locator, don't be alarmed by the IOC stuff :). This is really handy and a great way to solve your issue.

Binding to someviewmodel, assuming the vmlocator is defined in App.xaml and that SomeViewModel is present there.

DataContext="{Binding Source={StaticResource ViewModelLocator},  Path=SomeViewModel}"

Hope it helps,

Cheers Stian

Community
  • 1
  • 1
Stígandr
  • 2,874
  • 21
  • 36