Where and how should selected items be managed in a MVVM architecture? - wpf

I have a view that allows the user to select some data : some dates for example, and executes a command that needs these data.
So in my command I should have a reference to the selected date, but what is the best practice to make this date go to the ViewModel side where the command lives :
to add a SelectedDate dependency property in the ViewModel and bind my view on it, and reference it in my command via "#this.SelectedDate" (with #this a reference to the current ViewModel),
to let the view transmit it through the "parameter" of the "Execute" method of the command, and reference the date with "DateTime selectedDate = (DateTime)parameter;",
any other solution...
Thanks by advance.

I'd make SelectedDate a dependency property of the view model, absolutely.
I'd also make the command get the SelectedDate from the view model. There's no reason for the view to know anything about that.

To the first part, Yes I think the SelectedDate should be an (INotify) property of your ViewModel.
I don't have a strong opinion on where your Command should obtain this information, I think the property is OK.

The BookLibrary sample application of the WPF Application Framework (WAF) shows a way to handle the selected item with MVVM: The ViewModel has a 'SelectedBook' property which is bound to the View.

Related

WPF: How to trigger GUI behaviours in response to view-model events?

I'm developing a WPF/MVVM application and I have a listbox binding to data in a ViewModel. At various points I need the view model to cause the listbox to scroll to a given element.
How can I do this without creating a custom control and while still maintaining good separation of concerns?
I've currently got it working by creating a custom behavior class in the view layer with a dependency property VisibleIndex which the XAML code then binds to an integer in the view model:
<ListBox x:Name="myListBox"
local:ListBoxVisibilityBehavior.VisibleIndex="{Binding VisibleIndex}">
When the integer is set it triggers the dependency properties update handler which tells the listbox to scroll to the associated index.
This seems a bit hacky though because the dependency property value is never changed by the listbox and the update handler only gets called when the value changes, so the only way to ensure that the relevent item is visible is to do something like this:
// view-model code
this.VisibleIndex = -1;
this.VisibleIndex = 10;
The only reason I'm using a behaviour class at the moment is for binding my custom dependency property, is there a way to do something like this with events instead?
Attached properties are somewhat required in your case - as at some point, 'somewhere' you need to call the following method...
ListBox.ScrollIntoView(item)
or
ListBoxItem.BringIntoView();
And for that you need some sort of code behind - and attached properties/behaviors are a nice way of packaging that, w/o impacting your MVVM.
Having said that - if you just need to have your 'selected item' scrolled into view at all times (which is the case most of the time). Then you could use a different attached-property based solution (that again):
mvvm how to make a list view auto scroll to a new Item in a list view
All you have to do then is to set or bind to SelectedItem.
That's a bit 'nicer' if you wish - but the mechanism is the same.
For anyone else interested in the answer to this one of the MS engineers on the WPF forum cleared it up for me. Instead of binding to an event directly you bind to a wrapper object that encapsulates that event. The behaviour can then grab the reference to the wrapper from its DP and do whatever it wants with it i.e. subscribe to the event, trigger it etc.

How to access the ViewModel for a View

Let's say I have a simple View that displays a bit of text. The text comes from the View's ViewModel via a string property that is data bound. I would like to be able to set the ViewModel's string by multiple locations in the application.
What is the best practise for getting the instance of the ViewModel at the various points in my application?
I could make the ViewModel singleton but this didn't feel right.
Any suggestions?
I think there are different concepts for that.
Each has it's pros and cons....
1.) If you have have not parameters in the constructor of the view model you could use the DataContext Property of the Control, View, Page to bind the view model. It spin's up a instance per View...
2.) If you have complex or composed view models with constructor injections ... The best way would be the ViewModel Locator Pattern based on a Service Locator Pattern.
http://johnpapa.net/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum
http://blog.roboblob.com/tag/viewmodellocator/
3.) you have to think about view first or view model first and maybe about something like a view model marriage...
http://wildermuth.com/2009/5/22/Which_came_first_the_View_or_the_Model
HTH
i think you looking for something like a Messenger where your viewmodel can register for messages to change your string property and other components can send a message via messenger.
another approach is the PRISM event aggregator where you can subscribe to events when your string property should be changed.
EDIT: an other but bad way would be to give an instance of your viewmodel to all other locations. but then you have no more loose coupling.

How to call a user control method using MVVM?

I'm working in a WPF project, I'm using the MVVM patter in my project.
I created a user control (also in WPF) and I want to use it in my project, now, my problem is that I have a method in my user control that I need to call from my View Model, but I don't know how to do that, how to bind to the method inside my control from the view model.
If I use code behind, obviously there is no problem since I have a direct reference to my control, so I can do "mycontrol.MyMethod();"m, but of course, doing in this way will go against the logic of the MVVM pattern.
I tried to use a Dependency Property in my user control, and use that Dependency Property to bind to it in the xaml of my project but it didn't worked, the compiler says that the property was not found or is not serializable.
So I will appreciate if someone can share some light about how can I accomplish this.
Edited
As far as I understand you have the view, which is all the GUI, then you have the model, which is all the logic, and them you have the view-model which is like an intermediate layer used to bind the view with the model, right?
In this way I have developed my project, however I came to the problem that I need a custom control, a TextBox that remember what the user entered, and when he start typing, if there are words that start with that letter, those words are shown as a suggestion, as Google does it.
This TextBox is used as a search filter; so I created a user control to do this, I added a method to my user control to allow whatever application that uses my control to add items to an internal array that holds all the strings that the user has entered.
I created a user control because I couldn't find any control that behaves the way I want.
So my problem is when I add my user control to the main project, because I need to someway be able to call the method that add the items to the internal array, but maybe I'm doing things the wrong way, so if any of you has a better idea, I will appreciate if you shared it with me.
You should never call View methods from ViewModel, and vice versa.
Make a property (ObservableCollection?) on your ViewModel, it will have CollectionChanged event, subscribe to it to monitor changes (if needed).
When you add an item to the collection in your ViewModel, GUI will be updated accordingly (you have to perform the Add() operation on GUI thread, btw).
If you need to change the current position in your list, there are colections for that (CollectionViewSource, etc).
If you really really need to pass a string to your control, make a DependencyProperty and bind it OneWay to your ViewModel's property. When you set the value, it will call PropertyChangedCallback on your DependencyProperty.
Why does the consumer of the user control need to maintain the control's internal array? That seems like you've exposed an implementation detail that you don't need to.
Why not simply make that array a dependency property (and an IEnumerable<string> or ObservableCollection<string> besides)? Then you can simply create the corresponding property in your view model and bind it to the control. It also makes the control considerably more versatile.
You shouldn't call something in the View from the ViewModel since that breaks the model.
If the reason you want to call the method in the user control is to do with UI only, I don't see anything wrong with doing it from the view - the view's cs and the view's xaml are in the same "space" in the model. You can be overly-purist in wanting to have lean and mean view cs files.

Howto RadioButtons and MVVM pattern

I'm using PRISM (and thus the MVVM pattern). I've got a complex DateTime picker view with radio buttons.
The user can pick today, yesterday, a date, a week of a year, etc. I use radio buttons for the different choices.
What's the best way to do that in MVVM?
I really can't think of a clean way. I could create lots of custom behaviors to add to each item to track them but it doesn't seem maintainable.
I'm going to put some code-behind but I really don;t like that and to me it breaks the MVVM principle (put everything in the XAML).
Does anyone have a better idea on how to go about that?
Keep the RadioButtons, add an enum type to your VM that can return things like "Today" "Yesterday" or "Tomorrow." On the UI side create a ValueConverter that takes a parameter like "Tomorrow" and compares it with the bound value on VM, then returns the bool? needed by IsChecked.
Put it in code behind.
The M-V-VM pattern is not "put everything in xaml" it's "separate concerns". Your VM wants a DateTime right? In which case it doesn't care how that DateTime is being chosen it just needs a DateTime.
Putting View logic in the ViewModel isn't a good idea as you're now giving the VM knowledge about the workings of the View. The flow is meant to be View knows about the ViewModel which knows about the Model. The reverse is not normally true. (As with all things computer related there is always exceptions)
Hope this helps.
How about a ComboBox instead of the RadioButtons presenting a list of TimeOffset (custom class) bound to your ViewModel, with a corresponding SelectedTimeOffest property.
If you need to display extra information depending on the type of TimeOffset, e.g. a WeekOffset (subclass of TimeOfset) with a WeekCount property, have a content control with several DataTemplates customized by the type of TimeOFfset.
Just an idea...
you could create a enum, bind the values of the enum to a listbox, retemplate the ListboxItems
this post is using silverlight, but something similar should work
http://leeontech.wordpress.com/2009/03/18/creating-radiobuttonlist/
The ViewModel is designed to present the model in a way the view can consume.
In this case, you could have a boolean property for each button in the VM, and when a button updates it just sets all the other properties to false. Then in your View you can bind each properties IsChecked to the corresponding property in the ViewModel.
Also, be aware there is currently a bug in binding radio buttons in WPF. Here's a potential solution.

WPF Binding to a non-changing property

I'm using the MVVM pattern and I have a POCO (in my Model) with a Start Date property.
I want to show the elapsed time since the start date in a control on a WPF window/user control...
I don't see how I can bind a ModelView property to a UI control and have it update this duration automatically...can anyone suggest a way?
I could use something (a timer or a thread) to update a duration property on my ModelView but I just don't see any other way because as I understand it the UI will only update when a property value changes. However the start date on my POCO isn't changing it's just the elapsed time that's changing which is a calculated value.
Am I missing something?
You're on the right track. Have a look at the Presentation Model pattern on Martin Fowler's page.
The basic idea is to build a model for the UI (ViewModel) and have the UI just sync up with it. Every bit of information to be displayed in the UI, should have a corresponding field or property in the ViewModel (although they may be retrieved or derived from values in the Model) .. the ViewModel makes it easy to store the View State/Session State (such as the current selection of items in a UserList) which is not present the in the Model class behind.
Since you want to show the 'elapsed time since' value in the UI, your ViewModel should have a property caled ElapsedTimeSince. Your WPF View has a control which is data-bound to this property.
Now as per your need, ensure you have a thread/timer event that re-evaluates the property value periodically using the current time and the Model's StartDate property. Your UI should reflect the updated value.

Resources