Skip to main content
Windows Calculator implements the Model-View-ViewModel (MVVM) design pattern to achieve clean separation between the user interface and business logic. This pattern enables testability, maintainability, and a clear data flow throughout the application.

What is MVVM?

MVVM divides the application into three distinct layers:

Model

Business logic and data

View

User interface (XAML)

ViewModel

Mediator exposing Model data to View

The Three Layers

Model

The Model layer contains pure business logic with no knowledge of the UI. It’s responsible for calculations, data storage, and core application functionality.
In Calculator, the Model is the CalcManager project with three components:
  • CalculatorManager - Manages calculator modes, history, and memory
  • CalcEngine - Performs calculations and maintains state
  • RatPack - Provides infinite precision arithmetic

View

The View layer consists of XAML files that define the visual interface. Views should contain minimal code-behind logic.
<Page x:Class="CalculatorApp.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <!-- UI elements bind to ViewModel properties -->
    </Grid>
</Page>

ViewModel

ViewModels expose data from the Model in a format suitable for the View. They:
  • Implement INotifyPropertyChanged for data binding
  • Expose commands for user actions
  • Transform Model data for display
  • Contain no UI-specific code

Data Flow

The following diagram shows how data flows through the MVVM layers:

ViewModel Hierarchy

Calculator’s ViewModels form a hierarchy matching the View structure:
ApplicationViewModel (MainPage)
├── StandardCalculatorViewModel (Calculator.xaml)
├── DateCalculatorViewModel (DateCalculator.xaml)
└── UnitConverterViewModel (UnitConverter.xaml)

ApplicationViewModel

ApplicationViewModel is the root ViewModel corresponding to MainPage.xaml. It manages mode switching and coordinates child ViewModels.Location: src/CalcViewModel/ApplicationViewModel.h

Mode-Specific ViewModels

Supports Standard, Scientific, and Programmer calculator modes.Location: src/CalcViewModel/StandardCalculatorViewModel.hKey features:
  • Display value management
  • Expression tokens for display
  • History and memory management
  • Button command handlers
Handles date difference and date addition/subtraction calculations.Location: src/CalcViewModel/DateCalculatorViewModel.h
Manages all unit conversion modes including currency.Location: src/CalcViewModel/UnitConverterViewModel.h

Benefits of MVVM in Calculator

Testability

ViewModels can be tested without UI, enabling comprehensive unit tests for business logic.

Separation of Concerns

UI designers work on XAML while developers focus on ViewModels and Models independently.

Reusability

ViewModels can be reused across different Views or platforms.

Maintainability

Clear boundaries make the codebase easier to understand and modify.

Data Binding

MVVM relies heavily on data binding to connect Views and ViewModels:
Example: Binding in Calculator.xaml
<ItemsControl ItemsSource="{Binding ExpressionTokens}">
    <!-- Automatically updates when ExpressionTokens changes -->
</ItemsControl>
Calculator prefers x:Bind over Binding for better performance. See Data Binding for details.

Command Pattern

User actions trigger commands defined in ViewModels:
Button Command Binding
<Button Command="{x:Bind Model.CopyCommand}"/>
The ViewModel defines the command implementation:
StandardCalculatorViewModel.h
COMMAND_FOR_METHOD(CopyCommand, StandardCalculatorViewModel::OnCopyCommand);
The COMMAND_FOR_METHOD macro simplifies command creation by generating the necessary boilerplate code.

Property Change Notifications

When ViewModel properties change, the UI automatically updates through the INotifyPropertyChanged interface: See the ViewModel Layer documentation for implementation details.

Best Practices

Do not reference UI elements in ViewModels. ViewModels should have no knowledge of XAML controls or the View layer.
1

Keep Views Simple

XAML should be declarative. Move complex logic to ViewModels.
2

Use Data Binding

Prefer data binding over code-behind event handlers.
3

Observable Properties

Use OBSERVABLE_PROPERTY_RW for properties that trigger UI updates.
4

Commands for Actions

Expose user actions as commands, not public methods.

Example: Display Value Flow

Here’s how a calculation result flows through MVVM:
  1. User presses the ”=” button
  2. View (Calculator.xaml) executes ButtonPressed command
  3. ViewModel (StandardCalculatorViewModel) processes the command
  4. ViewModel calls Model (CalculatorManager)
  5. Model performs calculation via CalcEngine
  6. Model returns result to ViewModel
  7. ViewModel updates DisplayValue property
  8. RaisePropertyChanged("DisplayValue") fires
  9. View receives PropertyChanged event
  10. UI binding re-evaluates and updates display

Next Steps

View Layer

Explore XAML implementation

ViewModel Layer

Deep dive into ViewModels

Model Layer

Understand the calculation engine

Build docs developers (and LLMs) love