View Models
- 3 minutes to read
The View Model is a part of an MVVM application responsible for the interaction between the two other parts: Model and View.
Base View Models
The DevExpress MVVM Framework contains base classes that you can use to create your View Models:
- BindableBase
- Implements the INotifyPropertyChanged interface and allows you to implement bindable properties.
- ViewModelBase
- A BindableBase descendant that offers commands, services, and interaction between View Models.
Generated View Models
The MVVM Framework allows you to produce boilerplate code for your View Models, so that you do not need to implement each command or property:
- Runtime-generated POCO View Models
- Use the ViewModelSource.Create method to create a descendant of your View Model class. The mechanism is based on the Reflection Emit and produces code at runtime.
- View Models Generated at Compile Time
- Use attributes to generate a View Model. The mechanism is based on the Source Generators and produces code at compile time.
You can find the requirements for both techniques in the table below:
POCO View Models generated at runtime | View Models generated at compile time | |
---|---|---|
C# | v6+ | v9+ |
.NET Framework | v4.5.2+ | v4.6.1+ |
.NET Core | v3.0+ | v3.0+ |
Note
C# 9 is officially supported in .NET 5 and newer. You may encounter issues when you use earlier versions of .NET and .NET Framework.
The following table summarizes the differences between View Models generated at runtime and compile time:
POCO View Models generated at runtime | View Models generated at compile time | |
---|---|---|
Execution time | Runtime | Compile time |
Generated class | Descendant class | Partial class |
Generated code access | Read-only .cs file | |
Debug access | ||
VB support |
Dependency Injection
To bind a view to a view model, create a MarkupExtension that resolves the correct ViewModel type:
public class DISource : MarkupExtension {
public static Func<Type, object, string, object> Resolver { get; set; }
public Type Type { get; set; }
public object Key { get; set; }
public string Name { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider) => Resolver?.Invoke(Type, Key, Name);
}
Register the resolver at application startup:
protected override void OnStartup(StartupEventArgs e) {
base.OnStartup(e);
DISource.Resolver = Resolve;
}
object Resolve(Type type, object key, string name) {
if(type == null)
return null;
if(key != null)
return Container.ResolveKeyed(key, type);
if(name != null)
return Container.ResolveNamed(name, type);
return Container.Resolve(type);
}
Specify the DataContext in XAML in the following manner:
DataContext="{common:DISource Type=common:CollectionViewModel}"