WPF MVVM Problems with View
I want to use WPF with MVVM pa开发者_如何学Gottern in my project, but i am confused about some points regarding MVVM pattern. Please help me to clarify these points.
- I am using DataTemplate for ViewModel, but i want specific control to be keyboard focused.
- How can i focus specific control after ICommand Executed.
- How can i move focus to not validated control.
- Is there any way to separate DataTemplate depending on ViewModel property value.
- How can i validate all controls before ICommand
- Is there any other better approach to ask any confirmation from ViewModel with MessageBox
Regards, Mitan
I highly suggest you have a look at caliburn (or caliburn.micro) which exposes different UImanager interfaces so your viewmodel can do such things without losing unit testability.
To set the foucs on control use codebehind. MVVM doesn't say don't not use codebehind.
Write a method on code behind to set the focus and call this method from view model.
Example
public interface IView
{
void setFoucs();
}
//Code Behind
public class MyWindow : Window, IView
{
public void SetFoucs()
{
MyControl.Focus();
}
}
public class ViewModel
{
public IView _view { get; set; }
public ViewModel(IView view)
{
_view = view;
}
public void SomeMethod()
{
_view.SetFocus();
}
}
For question no 4 - I think your are looking to selecte specific datatemplate based on your some logic. To achieve this use DataTemplateSelector class.
http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector
Question 1:
Not clear what you mean/want. Generally the TabIndex controls the focus flow in your application, with silverlight it is however not as easy to configure as in windows forms. Silverlight also does a good job at setting the tab sequence automatically.
However, you should note that all controls inheriting from Control receive, by default, the focus. This incudes some controls that may be used as a container for other controls (e.g. ContentControl). This behaviour might lead to some unwanted effects. Use the IsTabStop
property to remove these controls from the tab order.
Question 2:
Well, it depends on how decoupled you want your application (the more decoupled the better). @pchajer's approach is one way of doing it, however it couples the view to the view model and this - although abstracted via an interface - is IMHO not a good idea for the following reasons:
- Usually the view model is pulled from a locator in order to allow for blendability. Now if I have to use code behind to pass the View to the ViewModel this might break it. Better would be if it could be injected into the ViewModel via a constructor parameter and this would then break the locator.
- The code becomes less testable as it now depends on the view. To make it testable you need to inject an implementaion of IView into the ViewModel, and this breaks the locator again.
Therefore, I would advise you to use Messaging to send a message to your view once the Command is complete. Then you can set the focus in the message handler. However, be aware that your might have to use the Dispatcher as the message handler could run in a separate thread.
Question 3:
You could capture the BindingValidationError on the control and then set the focus. Again be aware of possible threading issues.
Question 4:
Not sure, but if you mean that you want to use different DataTemplates based on whether a property has a certain value or not a TemplateSelector might help you. See http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-a-datatemplateselector.
Question 5:
The controls are validated when the property change event is fired, usually on the lost focus event. Your Model/ViewModel can implement IDataError to do the validation, and your can access this value from the CanExecute method associated with your command. However, you should try to keep the code in the CanExecute method as quick as possible as this method is called quite frequently.
Question 6:
You can implement your own Window that provides a custom layout. However, using the message box is a lot simpler. Again you should think of using messaging or a dialog service (e.g. http://blog.roboblob.com/2010/01/19/modal-dialogs-with-mvvm-and-silverlight-4/) to decouple your View and ViewModel. In fact there is even a DialogMessage in MVVMLight.
精彩评论