Skip to content

MVVM Architecture — Model-View-ViewModel Pattern (2026)

DodaTech Updated 2026-06-20 6 min read

In this tutorial, you'll learn how MVVM separates UI logic from business logic using data binding and a ViewModel as a state holder — a pattern dominant in modern frontend development. Why does this matter? Traditional MVC controllers struggle with complex UI state, leading to callback spaghetti and untestable presentation code. Real-world use: WPF applications, Angular components with services, Vue's reactive data layer, and SwiftUI's @State and @ObservedObject patterns.

What Is MVVM Architecture?

MVVM stands for Model-View-ViewModel, an architectural pattern where the ViewModel exposes data and commands from the Model as reactive properties that the View binds to. The key innovation is data binding — UI elements automatically update when the underlying data changes.

Think of a spreadsheet: the Model is the raw data cells, the View is the visible grid with formatting, and the ViewModel is a formula that derives calculated values and keeps everything synchronized automatically. You change one cell, and all dependent cells recalculate without manual refresh calls.

graph LR
    View -->|Data Binding| ViewModel
    ViewModel -->|Commands| View
    ViewModel -->|Updates| Model
    Model -->|Data Events| ViewModel
    
    style View fill:#2ECC71,color:#fff
    style ViewModel fill:#E67E22,color:#fff
    style Model fill:#7B68EE,color:#fff

How MVVM Works

MVVM relies on three core mechanisms: data binding, commands, and notification.

Data Binding

Data binding creates a live connection between the View and ViewModel. When the ViewModel property changes, the View updates automatically. This is two-way binding when user input flows back to the ViewModel.

// Angular component (View + ViewModel hybrid)
@Component({
  template: `<input [(ngModel)]="username">
             <p>Hello, {{ username }}!</p>`
})
export class LoginComponent {
  username: string = "";
}

ViewModel as State Holder

The ViewModel holds UI state — form data, loading flags, error messages — and exposes commands that the View can invoke:

// SwiftUI ViewModel
class UserProfileViewModel: ObservableObject {
    @Published var name: String = ""
    @Published var isLoading: Bool = false
    @Published var errorMessage: String? = nil
    
    func loadUser() {
        isLoading = true
        // fetch from Model...
        isLoading = false
    }
}

The View binds directly:

struct ProfileView: View {
    @ObservedObject var viewModel: UserProfileViewModel
    
    var body: some View {
        VStack {
            TextField("Name", text: $viewModel.name)
            if viewModel.isLoading {
                ProgressView()
            }
        }
    }
}

Command Pattern

MVVM replaces event handlers with commands — objects that encapsulate an action and its enabled state:

// WPF / XAML ViewModel
public class SaveCommand : ICommand {
    private readonly Func<Task> _execute;
    
    public bool CanExecute(object? parameter) => !IsBusy;
    
    public async void Execute(object? parameter) {
        IsBusy = true;
        await _execute();
        IsBusy = false;
    }
}

Data Flow

sequenceDiagram
    participant V as View
    participant VM as ViewModel
    participant M as Model
    
    V->>VM: User types in input
    VM->>VM: Updates property (two-way binding)
    VM->>M: Calls service/API
    M-->>VM: Returns data
    VM->>VM: Updates @Published/Observable property
    VM-->>V: Auto-renders via binding

Real-World Examples

WPF and XAML (Microsoft)

WPF introduced MVVM with .NET Framework 3.0. XAML views bind to ViewModel properties and commands. The ViewModel implements INotifyPropertyChanged and uses ICommand for actions. This makes UI code fully testable without creating windows.

Angular

Angular components act as the View (template) plus a partial ViewModel (class). Services serve as the Model layer. Two-way binding via [(ngModel)] and reactive forms make MVVM natural.

Vue.js

Vue's data() function returns a reactive state object, acting as the ViewModel. Computed properties derive values automatically. The template syntax {{ }} and v-model create declarative bindings.

SwiftUI

SwiftUI is Apple's MVVM framework. Views are lightweight structs describing the UI. ViewModels are ObservableObject classes with @Published properties. The @State, @ObservedObject, and @EnvironmentObject property wrappers manage data flow.

Pros and Cons

Pros Cons
Testable — ViewModels test without UI automation Overhead — extra classes for every view
Designer-developer workflow — designers work on XAML/HTML, developers on ViewModels Binding complexity — debugging binding failures is hard
Separation of concerns — UI logic isolated from business logic Memory leaks — forgotten subscriptions to observable properties
Reactive updates — UI stays in sync automatically Steep learning curve — beginners struggle with reactive programming
Platform flexibility — same ViewModel works for web, desktop, mobile Overkill for simple views — not every component needs a ViewModel

When to Use MVVM

MVVM shines when:

  • Complex UI state — forms with validation, loading states, error handling
  • Multiple UI platforms — share ViewModels between web, desktop, and mobile
  • Data binding support — the framework natively supports binding (WPF, SwiftUI, Angular)
  • Testability requirements — automated UI testing is critical

Skip MVVM for simple static pages, server-rendered applications without rich client interactions, or projects where the team lacks reactive programming experience.

FAQ

What is the difference between MVC and MVVM?

MVC uses a Controller that imperatively updates the View and Model. MVVM uses a ViewModel with data binding, so the View updates reactively. MVVM reduces controller code and is better for complex UI state management.

Is MVVM only for frontend?

MVVM is primarily a presentation pattern for UI applications. However, the ViewModel concept extends to mobile (Android ViewModel, SwiftUI ObservableObject) and desktop (WPF, WinUI). Backend APIs typically use MVC or Clean Architecture instead.

Does MVVM work with React?

React uses a unidirectional data flow (Flux/Redux) rather than MVVM's two-way binding. While you can approximate MVVM with custom hooks and state management, React's design philosophy favors explicit state updates over automatic binding.

What is INotifyPropertyChanged?

INotifyPropertyChanged is a .NET interface that notifies the View when a property changes. It's the foundation of data binding in WPF and Xamarin. The ViewModel fires a PropertyChanged event, and the View re-reads the bound property.

How do you test a ViewModel?

ViewModels are plain classes — no UI dependency. You instantiate the ViewModel, call commands, set properties, and assert that state changes correctly. This eliminates the need for UI automation frameworks in unit tests

  • MVC Architecture — the predecessor pattern
  • Observer Pattern — foundation of data binding
  • Clean Architecture — keep ViewModels as use case presenters
  • Dependency Injection — inject services into ViewModels

Practice Questions

  1. What are the three core components of MVVM, and how do they communicate?

  2. What is two-way data binding, and when would you use one-way binding instead?

  3. How does the command pattern benefit MVVM over traditional event handlers?

  4. Why is MVVM particularly suited for platforms like WPF and SwiftUI?

  5. What is the risk of memory leaks in MVVM, and how do you prevent it?

Challenge

Take an MVC controller that handles form validation, API calls, and error display. Refactor it into a ViewModel with observable properties and commands. The View should only bind to the ViewModel — no logic in the View layer.

Real-World Task

Open an Angular or Vue project. Identify each component's View and ViewModel responsibilities. Check for business logic in template expressions — move any logic into the component class (or a separate service). Verify that the ViewModel can be unit tested without rendering the component.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro