MVVM Blues...
-
Pete, I've started using MVVM Light. I'm slowly pulling pieces of it into my implementation. For example, I had written my own ViewModelBase class that encapsulates (is that the right word?) some common things that I needed for all of my classes. I changed the name of my base class and am now deriving it from Laurent's ViewModelBase, with all of my View Model classes still being derived from my modified base class. I was able to pull out some of the INPC stuff, etc. from my base class, and just use the MVVM Light implementation. Likewise, I threw away my homegrown (based on some of your code in fact) RelayCommand class and am using the MVVM Light version. There was nothing wrong with the homegrown version, but Laurent's is a bit more flexible. The Messenger class is the cat's a$$. I've found some good uses for that. I have not used the ViewModelLocator because I already had a scheme going that I like that was suggested to me by Collin Jasnoch, and it seems to be working well. All in all, I feel I am getting there. Thanks for the suggestions and encouragement. :thumbsup:
WE ARE DYSLEXIC OF BORG. Refutance is systile. Your a$$ will be laminated. There are 10 kinds of people in the world: People who know binary and people who don't.
Personally, I prefer using the ViewModelLocator method vs. DataTemplates. Some people are the other way around. I think the ViewModelLocator method is a lot cleaner and makes more sense. You load up a view and it should know how to do its own thing. Creating the VM first seems backwards to me. IMO, you shouldn't be creating VMs by hand. You should leave that to the view locator and DI. Also, the ViewModelLocator is 1 line in XAML vs. the DataTemplate method with is 3 lines of XAML + C# code to create the VM and set the DataContext.
-
Personally, I prefer using the ViewModelLocator method vs. DataTemplates. Some people are the other way around. I think the ViewModelLocator method is a lot cleaner and makes more sense. You load up a view and it should know how to do its own thing. Creating the VM first seems backwards to me. IMO, you shouldn't be creating VMs by hand. You should leave that to the view locator and DI. Also, the ViewModelLocator is 1 line in XAML vs. the DataTemplate method with is 3 lines of XAML + C# code to create the VM and set the DataContext.
I'll take your suggestions under advisement. For now, however, I'm going to leave that part of things alone. For this particular app, it is working well, and I have changed enough things around already. Maybe my next project. I need to get moving on this thing and get it finished up! ;) Thanks for the suggestions. I appreciate the input. :thumbsup:
WE ARE DYSLEXIC OF BORG. Refutance is systile. Your a$$ will be laminated. There are 10 kinds of people in the world: People who know binary and people who don't.
-
This is not really a question... When working with WPF trying to implement the MVVM pattern, I feel like I spend all of my time writing code to jump through hoops so as to not violate the MVVM pattern's principles... :sigh:
WE ARE DYSLEXIC OF BORG. Refutance is systile. Your a$$ will be laminated. There are 10 kinds of people in the world: People who know binary and people who don't.
I felt the same way when I first started MVVM, then I stepped back and reconsidered what the puropose of MVVM really is...To segregate your data and business layers from the UI. Read through this little example and you'll see my point at the end. Take for example double-clicking a list item. You want to know in the ViewModel what list item was double-clicked. You can bind the list's SelectedItem in the XAML to a property on the VM, but that handles clicking a list item, not double-clicking. To handle this, you need to handle the event. But that's not easy in MVVM. Here's what I do to handle something like this. In the View's code behind: First the XAML
Then in the code behind:
public MainPage()
{
InitializeComponent();
this.DataContext = new MainPageViewModel();
}then the event
private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ListBox list = sender as ListBox;
ListItem item = list.SelectedItem as MyBoundType;var dc = this.DataContext; dc.ListItemDoubleClicked(item);
}
This assumes a method in your VM called ListItemDoubleClicked that accepts a parameter of the type bound to your list. The point here is this - you can write code in your views that references your VM becuase the view already knows aout the VM. Just don't write any data-related code in the view's code behind and you're not violating VMMV.
Everything makes sense in someone's mind
-
I wrote my own MVVM framework probably 6 to 8 months ago. There were 10 to 12 open source ones available. I chose to reinvent (and improve) the wheel. 1) I didn't want the code cluster f*cked up with Silverlight (and other nonsense) support since I have no interest in that and it's a dead platform anyways 2) No MVVM framework out there provided 100% of the plumbing needed to write a full blown MVVM application. 50%? Absolutely. 75%? Probably. 90%+, sorry, but no. You'd have to combine 3 or 4 open source projects to get to where I'm at I think. Now granted, I may not have all the features of those 3 or 4 projects combined, but I have what is needed to write a full blown MVVM application and they don't. For example, none of them have a way of binding to multiple selection tree / list controls which I found to be quite important :).
Looking forward to your CP article on your framework :) best, Bill
"Science is facts; just as houses are made of stones: so, is science made of facts. But, a pile of stones is not a house, and a collection of facts is not, necessarily, science." Henri Poincare
-
I felt the same way when I first started MVVM, then I stepped back and reconsidered what the puropose of MVVM really is...To segregate your data and business layers from the UI. Read through this little example and you'll see my point at the end. Take for example double-clicking a list item. You want to know in the ViewModel what list item was double-clicked. You can bind the list's SelectedItem in the XAML to a property on the VM, but that handles clicking a list item, not double-clicking. To handle this, you need to handle the event. But that's not easy in MVVM. Here's what I do to handle something like this. In the View's code behind: First the XAML
Then in the code behind:
public MainPage()
{
InitializeComponent();
this.DataContext = new MainPageViewModel();
}then the event
private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ListBox list = sender as ListBox;
ListItem item = list.SelectedItem as MyBoundType;var dc = this.DataContext; dc.ListItemDoubleClicked(item);
}
This assumes a method in your VM called ListItemDoubleClicked that accepts a parameter of the type bound to your list. The point here is this - you can write code in your views that references your VM becuase the view already knows aout the VM. Just don't write any data-related code in the view's code behind and you're not violating VMMV.
Everything makes sense in someone's mind
The whole point of MVVM is not to have code in your code behind. You want your view abstracted from the business logic as well as the data it is bound to. This approach of directly calling an event in the code behind, tightly couples everything. To conform more with mvvm, rather re-route the event through a command.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
You will need to download: System.Windows.Interactivity.dll for the expression blend sdk. To use this functionality. I do believe that design patterns should only be used as a guideline for better development. not to be followed so strictly. But in this instance there is a better more mvvm type of solution. To what you suggesting with eventing.
-
The whole point of MVVM is not to have code in your code behind. You want your view abstracted from the business logic as well as the data it is bound to. This approach of directly calling an event in the code behind, tightly couples everything. To conform more with mvvm, rather re-route the event through a command.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
You will need to download: System.Windows.Interactivity.dll for the expression blend sdk. To use this functionality. I do believe that design patterns should only be used as a guideline for better development. not to be followed so strictly. But in this instance there is a better more mvvm type of solution. To what you suggesting with eventing.
The whole point of MVVM is not to have code in your code behind I completely disagree. The point of MVVM, or any design pattern for that matter, is separation of concerns, not "no code behind". No where in this does is mandate that you cannot have code in the code-behind. And, the view is already coupled to the view model when you do
this.DataContext = new MyViewModel();
The code I posted did not make any reference to the business or data layers, so it did not violate the design pattern. However, I do like the code you posted and agree that a command is the way to go. I posted my snippet as an example of calling into the VM from the view. Like I said, the two are already coupled, and the code didn't reference data or the BL, so there's no reason not to do it.
Everything makes sense in someone's mind
-
The whole point of MVVM is not to have code in your code behind. You want your view abstracted from the business logic as well as the data it is bound to. This approach of directly calling an event in the code behind, tightly couples everything. To conform more with mvvm, rather re-route the event through a command.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
You will need to download: System.Windows.Interactivity.dll for the expression blend sdk. To use this functionality. I do believe that design patterns should only be used as a guideline for better development. not to be followed so strictly. But in this instance there is a better more mvvm type of solution. To what you suggesting with eventing.
In your example above, what is the "cmd" in
Thanks
Everything makes sense in someone's mind
-
The whole point of MVVM is not to have code in your code behind I completely disagree. The point of MVVM, or any design pattern for that matter, is separation of concerns, not "no code behind". No where in this does is mandate that you cannot have code in the code-behind. And, the view is already coupled to the view model when you do
this.DataContext = new MyViewModel();
The code I posted did not make any reference to the business or data layers, so it did not violate the design pattern. However, I do like the code you posted and agree that a command is the way to go. I posted my snippet as an example of calling into the VM from the view. Like I said, the two are already coupled, and the code didn't reference data or the BL, so there's no reason not to do it.
Everything makes sense in someone's mind
You just said it yourself separation of concerns. If your code is in the code behind how is it a separation of concerns than. Thus it is counter productive to what you trying to achieve out of the pattern. Yes I agree to an extent that you shouldn't ever follow a pattern completely and only see it as a guideline. However what you were trying to achieve can be done without hooking up an event and finding the selected item. Like I've said previously you can do what you were trying to do in a far cleaner way. As far as initializing the ViewModel for the DataContext. Well that can also be done in xaml. There are many ways to skin a cat remember that. The key is to find the most flexible solution when testing and going forward. The question I ask is what if you want to change your viewModel? you have to go into the code behind and instantiate another object. Why don't you rather use a IOC container in this scenario. So you can have a more decoupled soltuion. ;)
-
In your example above, what is the "cmd" in
Thanks
Everything makes sense in someone's mind
A light MVVM framework called Galasoft
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
-
The whole point of MVVM is not to have code in your code behind. You want your view abstracted from the business logic as well as the data it is bound to. This approach of directly calling an event in the code behind, tightly couples everything. To conform more with mvvm, rather re-route the event through a command.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
You will need to download: System.Windows.Interactivity.dll for the expression blend sdk. To use this functionality. I do believe that design patterns should only be used as a guideline for better development. not to be followed so strictly. But in this instance there is a better more mvvm type of solution. To what you suggesting with eventing.
Dean Oliver wrote:
The whole point of MVVM is not to have code in your code behind.
That's not quite true. The idea in MVVM is not to have code that knows about the model in the code behind of the view. If you want to have code that handles something like a window resize, for instance (it's just an example, and yes you could perfectly easily accomplish this with attached behaviors), it's perfectly acceptable to have this in the code-behind; as long as it doesn't have any model knowledge.
*pre-emptive celebratory nipple tassle jiggle* - Sean Ewington
"Mind bleach! Send me mind bleach!" - Nagy Vilmos
My blog | My articles | MoXAML PowerToys | Mole 2010 - debugging made easier - my favourite utility