MVVM: Difference between revisions
Created page with "= MVVM Architecture (Model-View-ViewModel) = __TOC__ MVVM Architecture, short for Model-View-ViewModel is dominantly found in frontend development and used primarily in software development to separate concerns and enhance the modularity and testability of code. It facilitates a clear separation between the user interface (View) and the business logic (Model), with the ViewModel serving as an intermediary that handles the presentation logic. "This approach offers a way..." |
No edit summary |
||
| Line 66: | Line 66: | ||
<pre> | <pre> | ||
// Model: Person.cs | // Model: Person.cs | ||
public class Person | public class Person { | ||
{ | |||
public string FirstName { get; set; } | public string FirstName { get; set; } | ||
public string LastName { get; set; } | public string LastName { get; set; } | ||
| Line 81: | Line 80: | ||
using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||
public class PersonViewModel : INotifyPropertyChanged | public class PersonViewModel : INotifyPropertyChanged { | ||
{ | |||
private Person _person; | private Person _person; | ||
public PersonViewModel() | public PersonViewModel() { | ||
_person = new Person { FirstName = "John", LastName = "Doe", Age = 30 }; | _person = new Person { FirstName = "John", LastName = "Doe", Age = 30 }; | ||
} | } | ||
public string FirstName | public string FirstName { | ||
get { return _person.FirstName; } | get { return _person.FirstName; } | ||
set | set { | ||
if (_person.FirstName != value) { | |||
if (_person.FirstName != value) | |||
_person.FirstName = value; | _person.FirstName = value; | ||
OnPropertyChanged(); | OnPropertyChanged(); | ||
| Line 103: | Line 97: | ||
} | } | ||
public string LastName | public string LastName { | ||
get { return _person.LastName; } | get { return _person.LastName; } | ||
set | set { | ||
if (_person.LastName != value) { | |||
if (_person.LastName != value) | |||
_person.LastName = value; | _person.LastName = value; | ||
OnPropertyChanged(); | OnPropertyChanged(); | ||
| Line 116: | Line 107: | ||
} | } | ||
public int Age | public int Age { | ||
get { return _person.Age; } | get { return _person.Age; } | ||
set | set { | ||
if (_person.Age != value) { | |||
if (_person.Age != value) | |||
_person.Age = value; | _person.Age = value; | ||
OnPropertyChanged(); | OnPropertyChanged(); | ||
| Line 131: | Line 119: | ||
public event PropertyChangedEventHandler PropertyChanged; | public event PropertyChangedEventHandler PropertyChanged; | ||
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) | protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { | ||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); | ||
} | } | ||
| Line 162: | Line 149: | ||
using System.Windows; | using System.Windows; | ||
namespace WpfApp | namespace WpfApp { | ||
{ | public partial class MainWindow : Window { | ||
public partial class MainWindow : Window | public MainWindow() { | ||
public MainWindow() | |||
InitializeComponent(); | InitializeComponent(); | ||
DataContext = new PersonViewModel(); | DataContext = new PersonViewModel(); | ||
| Line 195: | Line 179: | ||
using System.Windows; | using System.Windows; | ||
namespace WpfApp | namespace WpfApp { | ||
{ | public partial class App : Application { | ||
public partial class App : Application | |||
} | } | ||
} | } | ||
| Line 209: | Line 191: | ||
using System; | using System; | ||
namespace WpfApp | namespace WpfApp { | ||
{ | public class Program { | ||
public class Program | |||
[STAThread] | [STAThread] | ||
public static void Main() | public static void Main() { | ||
var app = new App(); | var app = new App(); | ||
app.InitializeComponent(); | app.InitializeComponent(); | ||
Latest revision as of 16:00, 28 January 2025
MVVM Architecture (Model-View-ViewModel)
MVVM Architecture, short for Model-View-ViewModel is dominantly found in frontend development and used primarily in software development to separate concerns and enhance the modularity and testability of code. It facilitates a clear separation between the user interface (View) and the business logic (Model), with the ViewModel serving as an intermediary that handles the presentation logic.
"This approach offers a way to decouple user interface code from business logic, improving maintainability and testability." (Wikipedia)
Overview
MVVM Architecture promotes the idea of organizing code into three distinct components: Model, View, and ViewModel. This for a more maintainable codebase, as changes in the UI can be made independently of the business logic and vice versa. MVVM is particularly popular in applications with complex user interfaces, such as desktop applications and mobile apps.
Use Cases
MVVM Architecture is suitable for a variety of applications and scenarios, including:
- Desktop Applications: MVVM is commonly used in frameworks like WPF and Xamarin, which are tailored for rich desktop application development.
- Mobile Applications: Frameworks such as Android's Data Binding Library and Xamarin.Forms leverage MVVM to simplify UI development and testing.
- Rich Internet Applications: MVVM can be applied in web development using libraries like Knockout.js or Angular, enhancing the separation between the data model and UI components.
Benefits
- Separation of Concerns: MVVM clearly delineates the responsibilities of the UI and business logic, making the codebase more modular and easier to manage.
- Testability: By decoupling the business logic from the UI, MVVM makes it easier to write unit tests for the ViewModel and Model components.
- Maintainability: Changes to the user interface or the business logic can be made independently, reducing the risk of introducing bugs and making the application easier to evolve.
- Data Binding: MVVM facilitates two-way data binding, allowing automatic synchronization between the View and ViewModel, which reduces boilerplate code and enhances productivity.
Main Components
- Model: Represents the application's data and business logic. It is responsible for retrieving data from the database, performing calculations, and processing business rules. Encapsulates data and business logic. Examples include data models, business rules, and data access layers.
- View: Represents the user interface of the application. It displays data to the user and sends user input to the ViewModel. Defines the structure and layout of the user interface. Examples include UI elements like buttons, text boxes, and data grids.
- ViewModel: Acts as an intermediary between the View and the Model. It handles presentation logic, processes user input, and updates the View with changes from the Model. Manages the state of the View and handles user interactions. It binds data from the Model to the View and updates the Model based on user input.
MVVM Architecture Patterns
Two-Way Data Binding
Two-way data binding is a key feature of MVVM, allowing changes in the View to automatically propagate to the ViewModel and vice versa. This reduces the need for boilerplate code to manually update the UI or the data model, enhancing productivity and reducing errors.
Command Pattern
The Command Pattern is often used in MVVM to handle user actions. Commands are objects that encapsulate the information needed to perform an action, allowing the ViewModel to respond to user input without tightly coupling to the View.
Dependency Injection
Dependency Injection (DI) is a technique used in MVVM to manage dependencies and enhance testability. By injecting dependencies into the ViewModel, we can decouple the instantiation of components from their usage, making the codebase more flexible and easier to test.
Example: MVVM Architecture in a WPF Application
In a WPF (Windows Presentation Foundation) application, MVVM is commonly used to separate the UI from the business logic. The Model contains the application's data and business rules, the View defines the UI layout using XAML, and the ViewModel handles the presentation logic and data binding. This separation enables a clean and maintainable codebase, where changes to the UI or business logic can be made independently.
1. Create the Model
// Model: Person.cs
public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
2. Create the ViewModel
// ViewModel: PersonViewModel.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
public class PersonViewModel : INotifyPropertyChanged {
private Person _person;
public PersonViewModel() {
_person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };
}
public string FirstName {
get { return _person.FirstName; }
set {
if (_person.FirstName != value) {
_person.FirstName = value;
OnPropertyChanged();
}
}
}
public string LastName {
get { return _person.LastName; }
set {
if (_person.LastName != value) {
_person.LastName = value;
OnPropertyChanged();
}
}
}
public int Age {
get { return _person.Age; }
set {
if (_person.Age != value) {
_person.Age = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
3. Create the View
<!-- View: MainWindow.xaml -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="300">
<Grid>
<StackPanel>
<TextBox Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" Margin="10" />
<TextBox Text="{Binding LastName, UpdateSourceTrigger=PropertyChanged}" Margin="10" />
<TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}" Margin="10" />
</StackPanel>
</Grid>
</Window>
4. Create the View Code-Behind
// View: MainWindow.xaml.cs
using System.Windows;
namespace WpfApp {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = new PersonViewModel();
}
}
}
5. Create the App.xaml
<!-- App.xaml -->
<Application x:Class="WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
6. Create the App.xaml.cs
// App.xaml.cs
using System.Windows;
namespace WpfApp {
public partial class App : Application {
}
}
7. Create the Main Entry Point
// Program.cs
using System;
namespace WpfApp {
public class Program {
[STAThread]
public static void Main() {
var app = new App();
app.InitializeComponent();
app.Run();
}
}
}
8. Directory Structure
The project should have the following structure:
WpfApp/ ├── App.xaml ├── App.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Models/ │ └── Person.cs ├── ViewModels/ │ └── PersonViewModel.cs └── Program.cs
9. Running the Application
To run the application, ensure that your project is set up to start with the `Program.cs` entry point. You can do this by setting the startup object in your project properties.
Putting It All Together
With these components in place, the WPF application follows the MVVM pattern by separating the UI (View) from the business logic (Model), with the ViewModel acting as an intermediary to handle data binding and user interaction.