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

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!

Related

WPF Prism Unity Container. Setting keyboard focus on usercontrol or usercontrol grid parent

I'm working on a project that utilizes WPF, using the Prism library and Unity Container.
I have a mainwindow, which contains a mainviewmodel control which in turn is populated by a collection of user controls.
My goal is to set keyboard focus to the mainviewmodel where I have an EventTrigger InvokeCommandAction which reacts to keyeventsargs...
Currently the only way the command is fired if I use a textbox within the control (or child controls). My goal is to have the mainviewmodel control or grid get and preserve keyboard focus.
Any tips would be appreciated!
//Nathan
Either not understanding your question correctly or you should review the basic concepts of MVVM in a WPF implementation.
The View is the WPF controls.
WPF Window/UserControl files contain WPF markup which is the View.
Controls in a view leverage DataBindings to the DataContext property of either the control itself or the parent containing control (which it will inherit).
DataContext property is set to an instance of an object that is the ViewModel. It contains properties to hold values and commands to execute actions.
So conceptually there is no "mainviewmodel control", there is a MainView which contains controls and may in this case have its DataContext property set to an instance o MainViewModel. (hence my confusion)
Finally, while it is possible and some might even recommend writing UI rules/logic in a view model I haven't found much benefit in it.
You are much better off putting UI logic in the XAML or in the MinView code behind. You can still access the MainViewModel in the code behind by casting the MainView.DataContext property as a MainViewModel.
So for example:
MainView.KeyDown event can be wired up to call MainViewModel.CommandX.Execute();

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.

wpf: TextChanged event fired on setting DataContext

I've got a simple View with a single textbox that gets databound to a simple ViewModel with a single string property.
I need to catch the TextChanged event of that textbox so that I can do a little validation magic.
The problem that I am running into is that the TextChanged event fires for that textbox when the DataContext is set for the View.
Is there a standard mechanism that I can use to determine if the event is firing because of the DataContext being set versus when the user is making changes?
Thanks!
As far as I know there is no such mechanism. What you should do instead is to do your validation magic using standard means of WPF. Please see the following link: http://msdn.microsoft.com/en-us/library/ms752347.aspx#data_validation.
Anyway, as long as you use MVVM you can always detect that text has changed in the setter of the bound property in your view model.

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

Accessing controls from within commands in WPF

I've got a WPF app who's menu is using the commanding capabilities. Everything is wired up just fine and when I click the buttons in the menu, the commands run. However I'm having trouble getting the button's IsEnabled status to respect the CanExecute part of my commands.
One challenge is the commands need to see what you're doing in the UI. For instance, one command should only be available when certain items in a ListBox are selected so I need to get a reference to the ListBox... but since the command is exposed in my view model (MVVM pattern), it doesn't have access to the UI (BTW, the menu is in one user control [parent=mainwindow] while the ListBox is in another user control [parent=mainwindow]).
In addition, even when I hard code the command's CanExecute method to return false, the Enabled property of the button doesn't change... the command won't fire, but it won't change... frustrating. I assume I need to modify/raise the CanExecuteChanged event, but I'm not sure when I should be doing that (can't find a good sample).
Feedback?
Try the Messenger class from MVVMLight. It helps in communicating between ViewModels.
And give this a try:
Have a SelectedItem property in your ListBox's ViewModel. Broadcast messages while the property changes. Register for this message in the menu's ViewModel. Use the SelectedItem property in your CanExecute method for your logic.
Normally, you would bind the Command Property of the MenuItem/Button whatever - that means you still have the CommandParameter to work with - this can then be bound to some other control. However, when the two views do not know each-other, you need som kind of mediator between them (ie. a viewmodel that both views can access - have the listbox SelectedItem/SelectedItems bound to a property two-ways - and let the CommandParameter bind to the same property one-way).
As for when to fire the CanExecuteChanged event - you should fire that whenever there is a change in the logic contained in the CanExecute-method. If it is always false, you should never fire the event, as it will read the initalvalue when the Command-parameter is set. '
If your button is behaving oddly - check to see if the IsEnabled property is influenced by Styles or set directly.
Hope this helps.

Resources