If you know the MVVM pattern for WPF then you know Josh smith msdn article where a CustomerViewModel does not hold a simple property like:
public string FirstName {get;set;}
Rather a ViewModel wraps a Model and delegates the property access like this:
public string FirstName
{
get { return _customer.FirstName; }
set
{
if (value == _customer.FirstName)
return;
_customer.FirstName = value;
base.OnPropertyChanged("FirstName");
}
}
I have not seen this in asp.net mvc. Is this due to the missing INotifyPropertyChanged interface?
I have not seen this in asp.net mvc
That's normal. You shouldn't see it. MVC is a different pattern than MVVM. In MVC the view has nobody to notify of any changes. The MVVM pattern is not adapted to the stateless nature of the web.
The ViewModel and Model pieces from MVVM have a different definition than when used in MVC
In MVVM, the ViewModel is your application, while the View just provides a user-friendly interface for it. In MVC, the View is your application, the ViewModel provides data for it, and the Controller handles application flow and logic.
The Models are also different between the two patterns. In MVC, the M represents both data models and view models, while in MVVM the M only represents data models.
To summarize, MVC's M+C is equal to MVVM's VM, and MVC's M contains a mix of both MVVM's M and VM pieces
As a side note, the INotifyPropertyChanged interface is used by WPF to automatically update the UI when a property changes. This sort of thing is not used in MVC, so not needed.
Related
I need to send notification from ViewModel to View in MVVM WPF application. In most cases it will be simple MessageBox on View side. Is it unacceptable violation of MVVM pattern to use types like System.Windows.MessageBoxResult or System.Windows.MessageBoxImage in ViewModel (in this case VM must reference UI-specific libraries)?
I need to pass title, message and notification type from VM and by creating custom enumerations I am in fact copying existing functionality from .NET Framework.
You don't need notification mechanism. That's one option. Another is using simple service class:
public class ViewModel
{
IDialogService _dialogService; //ctor injection or use service locator
public void CommandExecute()
{
_dialogService.ShowMessageBox(...);
}
}
public interface IDialogService
{
bool? ShowMessageBox(params....);
}
public class DialogService : IDialogService
{
public bool? ShowDialog(params...)
{
MessageBox.Show(params...);
}
}
I find this approach more straightforward, easier to understand and easier to debug. Messaging may easily turn into memory leak and in this case I don't see any benefit over my approach.
EDIT:
Will you use custom enum in ShowMessageBox parameters, or will you use
System.Windows.MessageBoxImage?
First of all, ViewModels belong to presentation layer. It is OK to use enums like System.Windows.MessageBoxImage in ViewModel.
In MVVM, ViewModels are separated from Views because of following reasons:
ViewModels expose data and logic from Model in such way that is easily consumable from Views (e.g DataBinding)
ViewModels are easier testable
ViewModels provides better design time support (Blendability, test data)
ViewModels separates application logic from the actual presentation markup which makes it easier to understand (readbility)
Does using enum like System.Windows.MessageBoxImage breaks any of the points above? The answer is no.
If you wanted to reuse IDialogService and your ViewModels on multiple platforms, for example WPF, UWP and Xamarin, then you need to create your own enum, because it may not exist on all platforms. The golden rule is: don't add another layer of abstraction if you don't need it.
You could have the view implement an interface, say INotificationService and then pass the view to the view model constructor. That won't violate MVVM, and you will still be able to bind the view model to the view using the DataContext property on the view.
I decided to keep ViewModel as clean of UI (View) stuff as possible, so I will create custom enumeration inspired by MessageBox and tailored exactly to my needs.
I'm making the move from MVP to MVVM, and a little confused as to how best bind the ViewModel to the Model. I understand how we can leverage WPF's data binding infrastructure to route events between the View and ViewModel using ICommand and INotifyPropertyChanged interface, e.g., the View:
public class MyView
{
public MyView()
{
InitializeComponent();
DataContext = new MyViewModel();
}
}
and the ViewModel:
public class MyViewModel : INotifyPropertyChanged
{
public MyViewModel(){}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public ICommand MyCommand ...
}
This works great!
Now, typically with MVP I'd have my Presenter hold a reference to the Model via constructor injection, and raise events on the Model from the Presenter to update data in the Model. I tried the same approach with MVVM, but this requires the ViewModel to take the Model as a dependency in its constructor, which seems to make things a little messy with MVVM when using it straight out of the box without some form of IOC (with WPF at least).
So, my two questions are:
Is injecting the Model into the ViewModel the right approach, or should I be implementing INotifyPropertyChanged interface on the Model and making use of WPF's binding infrastructure?
To reap the benefits of MVVM, should you almost always implement it with IOC and a DI container, or better still Prism?
It is the "pure" MVVM approach: the View must depend only on the ViewModel. The ViewModel itself is a bridge between the View and Model.
The motivation — definition and responsibilities of the Model, View and ViewModel and also their relationships:
The Model, which provides a view-independent representation of your business entities. The design of the model is optimized for the logical relationships and operations between your business entities, regardless of how the data is presented in the user interface.
The View class which is the user interface. It displays information to the user and fires events in response to user interactions.
The ViewModel class, which is the bridge between the view and the model. Each View class has a corresponding ViewModel class. The ViewModel retrieves data from the Model and manipulates it into the format required by the View. It notifies the View if the underlying data in the model is changed, and it updates the data in the Model in response to UI events from the View.
-- Implementing the Model-View-ViewModel Pattern, MSDN.
Conclusion. Injecting the Model into the ViewModel seems to be the right approach. Also, instead of injecting Model it can be useful to inject:
the Model Factory to create the Model — lazy initialization;
the Service (Service Facade) to retrieve the Model — lazy loading.
As shown in the "MVVM Unleashed" book by Michael Brown, the following MVVM's potential benefits can be leveraged: maintainability, testability, "blendability", portability. At least, dependency injection (in the described case by using dependency injection container) allows a design to follow the Dependency Inversion Principle:
The principle of dependency inversion is at the root of many of the benefits claimed for object-oriented technology. Its proper application is necessary for the creation of reusable frameworks. It is also critically important for the construction of code that is resilient to change. And, since the abstractions and details are all isolated from each other, the code is much easier to maintain.
-- The Dependency Inversion Principle, Robert C. Martin, 1996.
As a result, such MVVM's benefits as the maintainability and testability seem to be improved when the Dependency Inversion Principle is followed. Dependency injection container is just a tool to follow the Principle.
I have a list of items representing packages in an MVVM control.
When you hover over the tooltip it needs to go to the database for additional information, lets just call it 'PackageDetails' for simplicity. I know how to handle the database loading with a ViewModel class but I'm having trouble figuring out when to instantiate it.
Approach 1) Have a 'lazy-load' property in the 'Package' object so when the tooltip is triggered the viewmodel will be created and immediately access the database.
This approach isn't ideal because each 'Package' object isn't a true viewmodel and came from WCF objects originally.
Approach 2) Use a converter as explained in this Josh Smith blog entry. His example seems to fit a converter well, but I don't think it really suits my situation well.
Approach 3) Somehow create a viewmodel in the XAML, but this seems like a bad idea.
What's a good approach to dynamically generate a viewmodel for a tooltip using MVVM
?
Binding models ( in your case the packages ) to the view only works for very simple situations where there is no more "processing" or business logic to implement.
I have experimented with a few options and in the ended up creating a VM wrapper for just about all my models. Going down this path makes having a tooltip property straight forward.
The other option that i have experimented with is to use partial classes to extend the wcf models. This works unless you are using dataannotations for validation ( wcf and dataannotations dont work together properly )
if you decide to wrap your models with a vm, then instantiating your list of VM wrappers is just one line of code using linq and lambdas
assuming you have a constructor on your VM that accepts your model as a parameter.
var listPackageVMs = new ObservableCollection<PackageVM> ( listPackageModels.Select(model=> new PackageVM(model)));
You could create a partial class to Package. I would avoid placing data access logic in an entity class, but this is the cheap and easy way.
namespace WCFServiceNamespace
{
// Since WCF generated entities are partial classes, we can inject features
public partial class Package
{
private readonly IDataAccessor _DataAccessor;
public Package()
: this(DataAccessor.Instance) // how you choose to inject a data accessor is up to you
{
}
public Package(IDataAccessor dataAccessor)
{
_DataAccessor = dataAccessor;
_ToolTip = new Lazy<string>(GetToolTip);
}
private readonly Lazy<string> _ToolTip;
public string ToolTip
{
get
{
// executes GetToolTip when the Value property of Lazy<T> is accessed
return _ToolTip.Value;
}
}
private string GetToolTip()
{
// we're assuming we can retreive the tooltip by ID, and that PackageId is defined in the generated WCF entity
return _DataAccessor.GetToolTipByPackageId(PackageId);
}
}
}
Following is excrept from this article on MVVM. Can someone provide example of how these other patterns (command, DI) are used in WPF? Are there any other desgin patterns that are used in WPF that you don't see listed here ?
There are other patterns you should be aware of to assist you in MVVM. Patterns like commanding (baked into WPF, solutions for SL), mediator and gasp dependency injection. .
I've written the article about some of them: WPF and Silverlight design patterns
Here is a brief description of the patterns:
1) MVVM - used as a model converter and as a replacement of the code-behind. Improves testability, it is much easier to write unit tests for ViewModel.
2) Dependency Injection - used for improving testability of a class (you can write unit tests for a specific class separately from others) and for the possibility to change implementation in easier way (change a logger, cache provider, web service etc)
3) Command - can be applied to Button and MenuItem controls by default, disables controls if an action can't be executed. Also used in MVVM pattern as a replacement of code-behind events.
Other patterns from the classic book which are already used in WPF:
Singleton. The Application class in WPF and the HttpContext class
in Web forms.
Adapter. The data-binding engine, which uses the IValueConverter
interface to convert binding values for the UI.
Decorator. The Border class, which decorates any UIElement class
with a border of variable thickness and color.
Façade. The PrintDialog class, which provides a simple interface
that enables you to use the entire printing and document subsystem
that WPF provides.
Command. The ICommand interface, which is implemented by the
RoutedCommand and RoutedUICommand classes.
Iterator. The IEnumerator interface, which many collections and lists
in the .NET Framework implement.
Observer. The INotifyPropertyChanged interface and events.
Data binding (between View and ViewModel) uses the Observer pattern. Also: the Factory pattern can be used to instantiate the ViewModel but that is optional.
Setter dependency injection:
When using MVVM you have to inject an instance of ViewModel into the View by setting it to the view.DataContext property:
var viewModel = new CustomViewModel();
var view = new CustomView();
view.DataContext = viewModel;
When using .NET RIA Services and MVVM in Silverlight 3.0 is there a difference between the Metadata type from RIA Services and the ViewModel from the MVVM pattern? Are these the same thing or should they be keep separate?
The metadata type is a sealed internal class to the partial Entity class. There doesn't seem to be a proper separation there but the metadata type can also be decorated with attributes for Validation which makes it look like a ViewModel.
I've searched around but I didn't see anything that talks about this in any detail.
Agree with ChuckJ - generally the DomainContext forms part of a view model. For example, say I had a search page that allowed searching against a product catalog. Here is how I'd structure things:
On the server:
class Catalog : DomainService {
IQueryable<Product> GetProducts(string keyword) { ... }
}
The generated DomainContext:
class Catalog : DomainContext {
EntityList<Product> Products { get; }
void LoadProducts(string keyword);
}
The view model I would write:
class SearchViewModel {
Catalog _catalog = new Catalog();
public IEnumerable<Product> Results {
get { return _catalog.Products; }
}
public void Search(string keyword) {
_catalog.Products.Clear();
_catalog.LoadProducts(keyword);
}
}
And then finally in my xaml, I'd set my UserControl's DataContext to be an instance of SearchViewModel, and bind an ItemsControl to the Results property. I'd use the ViewModel pattern of your choice to bind a button click to Search (which is effectively a command that SearchViewModel exposes). I personally like something that I have working with Silverlight.FX as in:
<Button Content="Search"
fxui:Interaction.ClickAction="$model.Search(keywordTextBox.Text)" />
and as initially shown here.
As Chuck mentions I might indeed have other state in my view model, for example, the SelectedProduct that might be two-way bound to the SelectedItem of a ListBox in my xaml, and then bind the same SelectedProduct as the DataContext of a DataForm to show details of a selected product.
Hope that helps! I'll be blogging about this some more on my blog soon.
The RIA services data context was designed to play the role of a ViewModel in the MVVM pattern since they natively support data binding, but they don't use that term in their documentation. However, it really depends. You will probably need state in your view model than the RIA data context provides such as commands and other view related state. I think what you want to do is use the data contexts from the RIA services as a part of the view model.