Introduction to UWP (Universal Windows Platform) — Quick Start
Categories:
- 1. Xaml
- 2. MVVM
- 3. Interaction Between ViewModel and Model
- 4. Interaction Between View and ViewModel
- 5. (View and ViewModel) Implementing Notifications – INotifyPropertyChanged
- 6. (View and ViewModel) ListView Binding to ObservableCollection
- 7. (View) ListView Item Templates (DataTemplate | UserControl)
- 8. (ViewModel and Model) Data Conversion – IValueConverter
- 9. (View) Modifying Control Styles
- 10. Using Panels
- 11. (View) Adaptive UI
- 12. Layout Principles
- 13. Localization
- 14. Naming Conventions
- 15. Notes
1. Xaml
1.1. XAML Introduction
- XAML Overview
- Primarily used to create visual UI elements.
- XAML syntax is based on XML.
- Declaring a namespace alias:
xmlns:controls="using:Common.Controls"
- Using classes from a namespace:
<controls:MyControl />
Reusable resources (Resource),
x:Key
<Style x:Key="TextBlock_Style" />
- Control element Name,
x:Name
XAML:
<MyControl x:Name="myControl" />
C#:
private MyControl myControl;
Localization
x:Uid
<TextBlock x:Uid="sampleText" />
1.2. Basic Controls – TextBlock, Button
<Page x:Class="MyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBlock Text="UWP Introduction" />
<Button Content="UWP Introduction" Click="Button_Click" />
</StackPanel>
</Page>
2. MVVM

- View should primarily contain UI presentation elements, mostly implemented in XAML;
- ViewModel should minimize business logic, delegating actions to Model functions;
- Model should encapsulate all business data and logic, with minimal dependency on View and ViewModel;
3. Interaction Between ViewModel and Model
3.1. ViewModel Manipulating Model Data
ViewModel:
public class ViewModel
{
private Model model;
private void ChangeA()
{
this.model.A = "A";
}
}
Model:
public class Model
{
public string A { get; set; }
public string B { get; set; }
}
3.2. Model Notifying ViewModel – event
ViewModel:
public class ViewModel
{
private Model model;
private void ChangeA()
{
model.BEventArgs += this.Handler;
}
private void Handler(object sender, EventArgs e)
{
AnyActions();
}
}
Model:
public delegate void BChangedHandler(object sender, EventArgs e);
public class Model
{
public string A { get; set; }
private string _B;
public string B
{
get { return this._B; }
set
{
this._B = value;
BEventArgs?.Invoke(this, new EventArgs());
}
}
public event BChangedHandler BEventArgs;
}
4. Interaction Between View and ViewModel
4.1. Data Binding
- Data Binding Overview
- Only DependencyProperty can be bound
- Bind to public Properties
- Refactor with caution
4.1.1. Binding to ViewModel
View:
<TextBlock Text="{Binding SampleText}" />
ViewModel:
public string SampleText { get; set; }
4.1.2. Binding to Other Controls
View:
<TextBlock x:Name="TextBlock1" Text="SampleText" />
<Button Content="{Binding ElementName=TextBlock1, Path=Text}" />
4.1.3. Specifying DataContext
public ViewModelClass ViewModel { get; set; }
...
SpecifiedControl.DataContext = ViewModel;
...
5. (View and ViewModel) Implementing Notifications – INotifyPropertyChanged
When SampleText changes, it notifies the bound DependencyProperty.
public class MyControlViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
private string _sampleText;
public string SampleText
{
get => _sampleText;
set
{
_sampleText = value;
Notify(nameof(SampleText));
}
}
}
Or inherit from ViewModelBase:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
6. (View and ViewModel) ListView Binding to ObservableCollection

Implement binding to an observable ItemSource in ListView.
View:
<ListView ItemsSource="{Binding Items}">
ViewModel:
public ObservableCollection<Recording> Items { get; set; }
- ObservableCollection only notifies when items are added/removed or the entire list is refreshed.
- To notify the UI when item content changes, Recording must implement INotifyPropertyChanged.
7. (View) ListView Item Templates (DataTemplate | UserControl)
7.1. DataTemplate
View:
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate DataType="local:Recording">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding A}" />
<TextBlock Text="{Binding B}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel:
public ObservableCollection<RecordingViewModel> Items { get; set; }
public class RecordingViewModel : INotifyPropertyChanged
{
...
// Implement INotifyPropertyChanged
...
private Recording _recording;
public string A
{
get => _recording.A;
set
{
_recording.A = value;
Notify(nameof(A));
}
}
public string B => _recording.B;
public RecordingViewModel(Recording recording)
{
_recording = recording;
}
}
Model:
public class Recording
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
... ...
}
Comparison:

7.2. UserControl
7.2.1. DependencyProperty
- Dependency Properties Overview
- Only DependencyProperty can bind to other properties, enabling notifications to View
- Has priority levels
View:
<control:MyControl Text="App is on searching" IsSearching="{Binding ViewModel.IsSearching}" />
ViewModel:
public class MyControl
{
...
public static readonly DependencyProperty IsSearchingProperty =
DependencyProperty.Register
(
"IsSearching", typeof(bool),
typeof(MyControl), null
);
public bool IsSearching
{
get => (bool)GetValue(IsSearchingProperty);
set => SetValue(IsSearchingProperty, value);
}
...
}
8. (ViewModel and Model) Data Conversion – IValueConverter
Use IValueConverter for data conversion between ViewModel and Model.
public class ShowAllButtonVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is IList list)
{
if (list.Count > 3)
{
return Visibility.Visible;
}
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
if (value is IList list)
{
if (list.Count > 3)
{
return Visibility.Visible;
}
}
return Visibility.Collapsed;
}
}
9. (View) Modifying Control Styles
9.1. Customizing Styles Within Controls
View:
<TextBlock Foreground="Red" Text="SampleText" />
9.2. Using Unified Styles – ResourceDictionary
View:
<Window.Resources>
<ResourceDictionary>
<Style TargetType="TextBlock" x:Key="ImportantText">
<Setter Property="Foreground" Value="Red" />
</Style>
</ResourceDictionary>
</Window.Resources>
...
<TextBlock Text="SampleText" Style="{StaticResource ImportantText}" />
9.3. Using ThemeResource
View:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<Style TargetType="TextBlock" x:Key="ImportantText">
<Setter Property="Foreground" Value="Red" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<Style TargetType="TextBlock" x:Key="ImportantText">
<Setter Property="Foreground" Value="Yellow" />
</Style>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<Style TargetType="TextBlock" x:Key="ImportantText">
<Setter Property="Foreground" Value="Black" />
</Style>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Window.Resources>
...
<TextBlock Text="SampleText" Style="{ThemeResource ImportantText}" />
10. Using Panels
10.1. Grid
Characteristics:
- Default Height/Width matches parent element.
Recommendations:
- Define child element layout sizes within Grid.
- Use proportional sizing.
10.2. StackPanel
Characteristics:
- Can exceed parent element boundaries.
- Height or Width adjusts based on panel content.
Recommendations:
- Use Padding and proportions flexibly.
- Assign Width or Height values to StackPanel in parent elements to prevent control overflow.
11. (View) Adaptive UI
- Use VisualStateManager.VisualStateGroup
<VisualStateGroup>
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger x:Name="WideLayoutTrigger" MinWindowWidth="1280" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SystemUpdateSideGrid.Width" Value="800" />
<Setter Target="SystemUpdateSideGrid.Grid.Row" Value="0" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="MidLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger x:Name="MidLayoutTrigger" MinWindowWidth="700" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="SystemUpdateSideGrid.Width" Value="400" />
<Setter Target="SystemUpdateSideGrid.Grid.Row" Value="1" />
</VisualState.Setters>
</VisualState>
...
</VisualStateGroup>
12. Layout Principles
- Avoid explicit element sizing.
- Do not use screen coordinates for element positioning.
- Child elements share available space within containers.
- Use nested layout containers.
13. Localization
- Use x:Uid for unique element identifiers:
<TextBlock x:Uid="S_TextBlock1" />
- Use Resources File:
<data name="S_TextBlock1.Text" xml:space="preserve">
<value>Sample text</value>
</data>
14. Naming Conventions
Big camel-case: firstName
Little camel-case: FirstName
- Class: big camel-case
- Property: big camel-case
- Field: little camel-case with prefix “_”
- Control in XAML: little camel-case
15. Notes
- Exercise caution when renaming ViewModel Properties, as XAML Binding names won’t update automatically during refactoring.