The Three Layers
Model holds data and business rules with no UI awareness; View is the UI layer — layout markup, styling, and rendering — with as little logic as possible; ViewModel sits between them, exposing observable state and commands derived from the Model, and it never holds a reference to any concrete View type. Data flows from Model through ViewModel to View via binding, and user actions flow back from View through commands into the ViewModel.
Cricket analogy: It's like the three roles at a match: the pitch and rulebook (Model) are fixed facts, the broadcast graphics (View) just display information, and the production truck's data feed (ViewModel) translates raw match data into what the graphics show.
Platform Building Blocks
The same pattern is implemented differently per platform: WPF and .NET MAUI use INotifyPropertyChanged for property change notification, ICommand for actions, and XAML {Binding} expressions to wire them up; Android uses the androidx ViewModel class combined with LiveData or Kotlin's StateFlow, consumed through Data Binding or Jetpack Compose's collectAsState; iOS/SwiftUI uses ObservableObject classes with @Published properties, consumed via @StateObject or @ObservedObject in the View.
Cricket analogy: It's like how the same sport of cricket is governed slightly differently across formats — Test, ODI, and T20 all share the same core rules but implement overs, fielding restrictions, and scoring differently.
// Minimal MVVM template for quick lookup (Kotlin / Android)
data class UiState(
val isLoading: Boolean = false,
val items: List<Item> = emptyList(),
val error: String? = null,
)
class ItemsViewModel(private val repo: ItemRepository) : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
fun load() = viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) }
runCatching { repo.fetchItems() }
.onSuccess { items -> _uiState.update { it.copy(isLoading = false, items = items) } }
.onFailure { e -> _uiState.update { it.copy(isLoading = false, error = e.message) } }
}
}Data Flow Cheat Sheet
The standard MVVM loop runs in one direction at a time: the View triggers a command or intent (button tap, text change) which calls a ViewModel method; the ViewModel calls into a use case or repository, updates its internal state, and publishes the new value through its observable property; the View, subscribed to that observable via binding, automatically re-renders. The View never reaches into the Model directly, and the ViewModel never reaches into the View — each arrow in the loop only ever points to its immediate neighbor.
Cricket analogy: It's like the chain from batter to scoreboard: the batter hits a boundary (command), the scorer updates the official record (state update), and only then does the digital scoreboard refresh for the crowd (re-render) — no step skips ahead.
Quick keyword lookup across platforms: WPF/.NET uses INotifyPropertyChanged and ICommand; Android uses MutableLiveData/MutableStateFlow and ViewModel; SwiftUI uses @Published, ObservableObject, @StateObject, and @ObservedObject. Same pattern, different keywords.
- Model = data and business rules; View = UI markup with minimal logic; ViewModel = observable state and commands, no View reference.
- WPF/.NET: INotifyPropertyChanged + ICommand + XAML {Binding}.
- Android: ViewModel class + LiveData/StateFlow + Data Binding or Compose's collectAsState.
- iOS/SwiftUI: ObservableObject + @Published + @StateObject/@ObservedObject.
- Data flow is unidirectional per step: View command -> ViewModel -> Model/use case -> updated state -> View re-render.
- The View never touches the Model directly, and the ViewModel never references the View.
- Use this page as a lookup, not a first introduction — pair it with the best-practices and pitfalls topics for full context.
Practice what you learned
1. Which statement correctly matches a layer to its responsibility in MVVM?
2. Which pairing correctly matches a platform to its MVVM building blocks?
3. In the standard MVVM data-flow loop, what does the View do when the user taps a button?
4. Which SwiftUI property wrapper does a View use to consume a ViewModel it owns and creates?
Was this page helpful?
You May Also Like
MVVM Best Practices
Practical guidelines for structuring ViewModels, bindings, and data flow so MVVM code stays maintainable at scale.
Common MVVM Pitfalls
The recurring mistakes teams make when adopting MVVM, from bloated ViewModels to memory leaks and broken separation of concerns.
MVVM Interview Questions
Frequently asked MVVM interview questions with model answers, covering architecture fundamentals, data binding, and comparisons to MVC/MVP.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics