Skip to main content
The View layer is contained in the Calculator project and consists of XAML files that define the user interface. This layer is responsible for rendering UI elements and capturing user input, while delegating all logic to the ViewModel layer through data binding.

Project Organization

src/Calculator/
├── App.xaml                # Application resources and theme definitions
├── App.xaml.cs            # Application entry point
└── Views/
    ├── MainPage.xaml      # Root container page
    ├── Calculator.xaml    # Standard/Scientific/Programmer
    ├── DateCalculator.xaml
    └── UnitConverter.xaml

Application Entry Point

App.xaml

App.xaml contains static and theme resources that other XAML files reference:
  • StaticResource: Fixed resources loaded once
  • ThemeResource: Resources that respond to theme changes

App.xaml.cs

The main entry point navigates to MainPage on startup:
src/Calculator/App.xaml.cs
rootFrame.Navigate(typeof(MainPage), argument)

Page Structure

MainPage.xaml

MainPage is the only concrete Page class in Calculator. It serves as the root container for all UI elements.
Key features:
  • Uses NavigationView control for the mode menu
  • Contains empty containers for delay-loaded UI
  • Manages mode switching
<Page x:Class="CalculatorApp.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
      x:Name="PageRoot"
      muxc:BackdropMaterial.ApplyToRootOrPageBackground="True"
      Loaded="OnPageLoaded">
    
    <Grid>
        <!-- VisualStateManager for adaptive layouts -->
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="Mode">
                <VisualState x:Name="ConverterWide">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="640"/>
                    </VisualState.StateTriggers>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        
        <!-- NavigationView and content containers -->
    </Grid>
</Page>

UserControls

Calculator uses three main UserControls to support all modes:

Calculator.xaml

Container for Standard, Scientific, and Programmer modes

DateCalculator.xaml

Date calculation interface

UnitConverter.xaml

All converter modes including currency

Calculator.xaml

This UserControl is a container that hosts three operator panels:
  • CalculatorStandardOperators.xaml - Basic operations
  • CalculatorScientificOperators.xaml - Scientific functions
  • CalculatorProgrammerOperators.xaml - Bitwise operations
<UserControl x:Class="CalculatorApp.Calculator"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:vmcommon="using:CalculatorApp.ViewModel.Common"
             Loaded="OnLoaded">
    
    <UserControl.Resources>
        <!-- Data templates for expression tokens -->
        <DataTemplate x:Key="Operand" x:DataType="vmcommon:DisplayExpressionToken">
            <TextBlock Margin="2,0,0,0"
                       Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
                       Text="{x:Bind Token, Mode=OneWay}"/>
        </DataTemplate>
        
        <DataTemplate x:Key="Operator" x:DataType="vmcommon:DisplayExpressionToken">
            <TextBlock Margin="2,0,0,0"
                       Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}"
                       Text="{x:Bind Token, Mode=OneWay}"/>
        </DataTemplate>
    </UserControl.Resources>
    
    <!-- UI layout -->
</UserControl>

VisualStates

VisualStates are critical for Calculator’s adaptive UI. When making UI changes, always consider all defined VisualStates.
VisualStates change the size, position, and appearance of UI elements to create responsive, adaptive layouts. Transitions are typically triggered by window size changes.

Key VisualState Examples

In Standard, Scientific, and Programmer modes, the History/Memory panel adapts based on window size:
  • Small window: Panel appears as a flyout overlay
  • Large window: Panel docks along the edge
VisualState Example
<VisualState x:Name="DockVisible">
    <VisualState.StateTriggers>
        <AdaptiveTrigger MinWindowWidth="560"/>
    </VisualState.StateTriggers>
    <!-- Setters to dock the panel -->
</VisualState>

VisualState Implementation

VisualStates are defined in XAML using VisualStateManager:
VisualStateManager
<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="Mode">
        <VisualState x:Name="ConverterWide">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowHeight="{StaticResource AppMinWindowHeight}" 
                                MinWindowWidth="640"/>
            </VisualState.StateTriggers>
            <VisualState.Setters>
                <!-- Property changes for this state -->
            </VisualState.Setters>
        </VisualState>
        
        <VisualState x:Name="MinSizeLayout">
            <VisualState.StateTriggers>
                <AdaptiveTrigger MinWindowWidth="{StaticResource AppMinWindowWidth}"/>
            </VisualState.StateTriggers>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Always test UI changes across all VisualStates and window sizes to ensure responsive behavior.

Data Binding

Calculator uses data binding to connect XAML UI elements to ViewModel properties, enabling automatic UI updates.

x:Bind vs Binding

Calculator uses two data binding syntaxes:
Modern, compiled binding with better performance:
x:Bind Example
<ItemsControl ItemsSource="{x:Bind Model.ExpressionTokens, Mode=OneWay}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsStackPanel HorizontalAlignment="Right" 
                             Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
Benefits:
  • Compile-time validation
  • Better performance
  • Supports function binding

Binding Modes

OneWay

ViewModel → ViewMost common for display

TwoWay

ViewModel ↔ ViewFor editable fields

OneTime

Single initial valueFor static content

Data Binding Example

Here’s how expression tokens are displayed:
Expression Token Binding (src/Calculator/Views/Calculator.xaml)
<ScrollViewer x:Name="ExpressionContainer">
    <ItemsControl x:Name="TokenList"
                  ItemTemplateSelector="{StaticResource ExpressionItemTemplateSelector}"
                  ItemsSource="{Binding ExpressionTokens}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <ItemsStackPanel HorizontalAlignment="Right"
                                 Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</ScrollViewer>
The ExpressionTokens property is defined in StandardCalculatorViewModel:
src/CalcViewModel/StandardCalculatorViewModel.h
OBSERVABLE_PROPERTY_R(
    Windows::Foundation::Collections::IObservableVector<Common::DisplayExpressionToken ^> ^, 
    ExpressionTokens
);
When ExpressionTokens changes, the ViewModel raises a PropertyChanged event, and the UI automatically updates.

Custom Controls

Calculator includes custom controls for specialized functionality:
  • OverflowTextBlock - Handles text overflow with scrolling
  • CalculatorButton - Customized button with calculator-specific behavior
  • CalculationResult - Display component for results

Command Binding

User actions trigger commands defined in ViewModels:
Command Binding (src/Calculator/Views/MainPage.xaml)
<Button x:Name="CopyButton"
        Command="{x:Bind Model.CopyCommand}"/>
        
<Button x:Name="PasteButton"
        Command="{x:Bind Model.PasteCommand}"/>
These buttons are hidden (for keyboard shortcuts) but their commands are bound to ViewModel methods.

Resource Management

Resources are defined at multiple levels:
1

Application-Level (App.xaml)

Global resources like fonts, colors, and styles used throughout the app.
2

Page-Level (MainPage.xaml)

Page-specific resources like data templates and converters.
3

Control-Level

Resources scoped to individual UserControls.

Best Practices

Use x:Bind for better performance and compile-time validation. Update legacy Binding expressions when modifying existing code.
UI changes should be tested across all defined VisualStates and window sizes.
Use code-behind only for View-specific logic like animations. Business logic belongs in ViewModels.
Avoid manual UI updates. Let data binding handle synchronization between View and ViewModel.

Next Steps

ViewModel Layer

Learn how ViewModels provide data to Views

MVVM Pattern

Understand the overall architecture pattern

Build docs developers (and LLMs) love