WPF Calendar: Binding to MVVM commands? - wpf

I am wiring up a WPF calendar to an MVVM view model. I'm not sure how to bind date selections and month changes to MVVM ICommand objects. For example to process a selected date change, what object would I bind in XAML to the appropriate command property in my view model?
As nearly as I can tell, I am stuck with event handling in code-behind. For example, it looks like the only way to detect a date selection change is to write a SelectedDatesChanged event handler. I can invoke the command property in my view model from the event handler, like this:
private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
{
var viewModel = (CalendarViewModel) DataContext;
viewModel.GetDateNotes.Execute();
}
But I sense a code smell to that approach, unless there is no better approach available. Can anyone tell me how to bind a WPF Calendar to MVVM commands directly from XAML? Is there a better approach than the one I am taking? Thanks for your help.

Wouldn't you have a DateTime property in your VM that is bound to the calendar and that raises PropertyChanged? If so, can't you watch for property changed internally or write code in your setter so that you know when the view has changed its value?

Related

MVVM pattern - executing view operations

I'm using MVVM Pattern (with MVVM Light) to build my XAML app (win8). I have a ListView, which is bound to a property of my ViewModel. I also have a button that triggers an operation on that ViewModel, which updates that property (which results in updating the ListView). The button uses commanding to execute the operation on the ViewModel. So far so good.
The problem is that after the list is refreshed I need to perform an operation that strictly belongs to my View, not to the ViewModel. It should scroll the list to a specific item. How to trigger that operation? Should I use a specific ListView event?
Using an EventHandler and the ScrollIntoView(Object) method you can achieve what you want without using references of the View inside the ViewMovel and respecting MVVM pattern.
Create an event in your ViewModel like this:
public event EventHandler ScrollListView;
In your View add a callback to scroll the ListView when the property is updated:
ViewModel vm;
vm.ScrollListView += (sender, e) =>
{
var specificItem = **some item**;
MyListView.SelectedItem = specificItem;
MyListView.UpdateLayout();
MyListView.ScrollIntoView(MyListView.SelectedItem);
};
Then in your ViewModel when you update that property and want to scroll the ListView:
if (this.ScrollListView != null)
{
this.ScrollListView(this, EventArgs.Empty);
}
This is how I usually do with some tweaks for each case of course.
The ViewModel is there to decouple the UI Code from the UI Design (E.g. XAML). [Separation of Concerns of Designer and Developer, Automated testing of UI Code, etc]
Ideally the code-behind file of the View will be empty (except the call to InitializeComponent) and all UI logic and state will be handled by the ViewModel. However, in practice there might be some specific UI manipulation that cannot be handled by data-binding alone and you will need to resort to code. Such code should be placed in the code-behind.
In your case, the logic for (a) when and (b) which item to scroll to must be in the ViewModel (not in the View). Only any additional logic required to perform the actual scrolling in the ListView will be in the View code-behind.
Yes, an event would be the ideal way to do this, to avoid having any references to the View inside the ViewModel. I would recommend however to create a custom event in the ViewModel (e.g. OnFirstItemInViewChanged with arguments the item to scroll to) and in the View code-behind register to this event and just call ListView.ScrollIntoView(item).
Note:
WinForms DataGridView had a property FirstDisplayedScrollingRowIndex. If there was something similar in WPF ListView, you could solve this by binding this property to a ViewModel property, therefore leaving the code-behind completely clean.

Event firing before databinding is updated - how do I wait for the update?

I'm currently encountering this issue while programming Metro, but I'm sure it applies to WPF, Silverlight and possibly even WinForms.
I have a databound TextBox and a method attached to the LostFocus event of the TextBox. When it loses focus, I want the code behind to trigger a save function in order to persist the data. The problem is that the LostFocus-event triggers before the business object is updated from the GUI through TwoWay databinding.
What is the best way to handle this? Is there some way to force update of the databinding from the LostFocus method (would probably be platform-specific)?
It sounds like you're wanting to do some business logic instead of having the GUI update the textbox. I would set the Textbox to only be BindingMode.OneWay, so that when the business object is changed the textbox is updated properly.
Then in the Lostfocus event (again wpf, but I think you'll get the idea):
private void EditBoxLostFocus( object sender, KeyboardFocusChangedEventArgs e )
{
var textbox = sender as TextBox;
//update your business object w/ textbox.Text value
//other business logic
}
This way you're in full control of when the object gets updated, and can apply your business rules.
Set UpdateSourceTrigger = PropertyChanged on the TextBox binding.
http://msdn.microsoft.com/en-us/library/system.windows.data.updatesourcetrigger(v=vs.100).aspx

WPF and MVVM: Enable a command only when a textbox has focus with implementation in ViewModel?

I have a command that I would like to be enabled only when a certain control has focus. I can do this with a routed command and command binding, but I'd like to keep the implementation in my ViewModel.
Is a command binding and an event handler in the code behind the only way?
To handle this within the ViewModel, you will need to add the concept of the 'certain control' having focus into your view model, enabling the command when this focus state changes.You could do this by adding a boolean IsCertainControlFocussed property to your view model.
To update this state you have two options, either handle the GotFocus and LostFocus events in the code behind of you view and set this boolean property on your view model. Or use one of the MVVM framework absraction mechanisms. For example the MVVM Light framework has an EventToCommand behaviour which allows you to wire an event to a command exposed by your view model, which could set this property.
http://geekswithblogs.net/lbugnion/archive/2009/11/05/mvvm-light-toolkit-v3-alpha-2-eventtocommand-behavior.aspx
Which technique you use depends on how important it is to you to have no code-behind. Personally I do not follow this religiously, as long as the View Model has the right responsibilities, and is testable, a little it of code behind does no harm!

WPF - Handling events from user control in View Model

I’m building a WPF application using MVVM pattern (both are new technologies for me). I use user controls for simple bits of reusable functionality that doesn’t contain business logic, and MVVM pattern to build application logic. Suppose a view contains my user control that fires events, and I want to add an event handler to that event. That event handler should be in the view model of the view, because it contains business logic. The question is – view and the view model are connected only by binding; how do I connect an event handler using binding? Is it even possible (I suspect not)? If not – how should I handle events from a control in the view model? Maybe I should use commands or INotifyPropertyChanged?
Generally speaking, it is a good MVVM-practice to avoid code in code behind, as would be the case if you use events in your user controls. So when possible, use INotifyPropertyChanged and ICommand.
With that said, depending on your project and how pragmatic you are, some times it makes more sense to use the control's code behind.
I have at a few occasions used something like this:
private void textBox1_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
MyViewModel vm = this.DataContext as MyViewModel;
vm.MethodToExecute(...);
}
You could also consider Attached Command Behaviour, more info about this and implementations to find here:
Firing a double click event from a WPF ListView item using MVVM

TextBox.TextChanged & ICommandSource

I am following the M-V-VM pattern for my WPF UI. I would like to hook up a command to the TextChanged event of a TextBox to a command that is in my ViewModel class. The only way I can conceive of completing this task is to inherit from the TextBox control, and implement ICommandSource. I can then instruct the command to be fired from the TextChanged event. This seems to be too much work for something which appears to be so simple.
Is there an easier way (than subclassing the TextBox and implementing ICommandSource) to hook up the TextChanged event to my ViewModel class?
First off, you've surely considered two-way data binding to your viewmodel, with an UpdateSourceTrigger of PropertyChanged? That way the property setter of the property you bind to will be called every time the text is changed?
If that's not enough, then I would tackle this problem using Attached Behaviours. On Julian Dominguez’s Blog you'll find an article about how to do something very similar in Silverlight, which should be easily adaptable to WPF.
Basically, in a static class (called, say TextBoxBehaviours) you define an Attached Property called (perhaps) TextChangedCommand of type ICommand. Hook up an OnPropertyChanged handler for that property, and within the handler, check that the property is being set on a TextBox; if it is, add a handler to the TextChanged event on the textbox that will call the command specified in the property.
Then, assuming your viewmodel has been assigned to the DataContext of your View, you would use it like:
<TextBox
x:Name="MyTextBox"
TextBoxBehaviours.TextChangedCommand="{Binding ViewModelTextChangedCommand}" />
Using the event binding and command method might not be the right thing to use.
What exactly will this command do?
You might want to consider using a Databinding to a string field in your VM. This way you can make a call to a command or function from there rather than having the UI care at all.
<TextBox Text="{Binding WorldName}"/>
....
public string WorldName
{
get
{
return WorldData.Name;
}
set
{
WorldData.Name = value;
OnPropertyChanged("WorldName");
// CallYourCustomFunctionHere();
}
}
Can you not just handle the TextChanged event and execute the command from there?
private void _textBox_TextChanged(object sender, EventArgs e)
{
MyCommand.Execute(null);
}
The alternative, as you say, is to create a TextBox that acts as a command source, but that does seem like overkill unless it's something you're planning on sharing and leveraging in many places.

Resources