UWP(Universal Windows Platform)-Einführung — Schnellstart
Categories:
- 1. Xaml
- 2. MVVM
- 3. Interaktion zwischen ViewModel und Model
- 4. Interaktion zwischen View und ViewModel
- 5. (View und ViewModel) Benachrichtigungen implementieren – INotifyPropertyChanged
- 6. (View und ViewModel) ListView an eine Quelle mit Benachrichtigungen binden – ObservableCollection
- 7. (View) Item-Vorlage (DataTemplate | UserControl) der ListView
- 8. (ViewModel und Model) Datenkonvertierung – IValueConverter
- 9. (View) Style des Controls ändern
- 10. Panel verwenden
- 11. (View) Adaptive UI (Adaptive UI)
- 12. Layout-Prinzipien
- 13. Lokalisierung (Localization)
- 14. Namenskonventionen
- 15. Hinweise
1. Xaml
1.1. XAML-Einführung
- XAML-Übersicht
- Wird hauptsächlich zum Erstellen visueller UI-Elemente verwendet.
- Die grundlegende Syntax von Xaml basiert auf XML.
- Einen Alias für einen Namespace deklarieren:
xmlns:controls="using:Common.Controls"
- Eine Klasse verwenden, die im Namespace deklariert ist:
<controls:MyControl />
Wiederverwendbare Ressourcen (Resource),
x:Key
<Style x:Key="TextBlock_Style" />
- Der Name des Steuerelementelements,
x:Name
Xaml:
<MyControl x:Name="myControl" />
C#:
private MyControl myControl;
Lokalisierung
x:Uid
<TextBlock x:Uid="sampleText" />
1.2. Die grundlegendsten Steuerelemente (Control) – 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 sollte nach Möglichkeit nur Inhalte für die UI-Darstellung enthalten; View wird meistens mit der Sprache Xaml erstellt;
- ViewModel sollte nach Möglichkeit keine Geschäftslogik enthalten, sondern Aktionen durch Aufruf von Funktionen im Model ausführen;
- Model sollte nach Möglichkeit alle Geschäftsdaten und -logiken enthalten und nach Möglichkeit nicht von View und ViewModel abhängen;
3. Interaktion zwischen ViewModel und Model
3.1. ViewModel steuert Daten des Models
ViewModel:
public class ViewModel
{
private Model model;
private ChangeA()
{
this.model.A = "A";
}
}
Model:
public class Model
{
public string A { get; set; }
public string B { get; set; }
}
3.2. Model benachrichtigt ViewModel – event
ViewModel:
public class ViewModel
{
private Model model;
private ChangeA()
{
r.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;
if (BEventArgs != null)
{
BEventArgs(this, new EventArgs());
}
}
}
public event BChangedHandler BEventArgs;
}
4. Interaktion zwischen View und ViewModel
4.1. Datenbindung
- Übersicht zur Datenbindung
- Nur DependencyProperty können gebunden werden
- Bindung an eine öffentliche Property (Public Property)
- Vorsicht beim Refactoring
4.1.1. Bindung an ViewModel
View:
<TextBlock Text={Binding SampleText} />
ViewModel:
public string SampleText { get; set; }
4.1.2. Bindung an andere Controls
View:
<TextBlock x:Name="TextBlock1" Text="SampleText" />
<Button Content="{Binding ElementName=TextBlock1, Path= Text}" />
4.1.3. DataContext angeben
public ViewModelClass ViewModel { get; set; }
...
SpecifiedControl.DataContext = ViewModel;
...
5. (View und ViewModel) Benachrichtigungen implementieren – INotifyPropertyChanged
Wenn sich SampleText ändert, wird das an dieser Property gebundene DependencyProperty benachrichtigt
public class MyControlViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string propName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
private string _sampleText;
public string SampleText
{
get
{
return _sampleText;
}
set
{
_sampleText = value;
Notify(nameof(SampleText));
}
}
}
Oder von ViewModelBase erben
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string propName)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
6. (View und ViewModel) ListView an eine Quelle mit Benachrichtigungen binden – ObservableCollection

Bindung an einen ItemSource mit Benachrichtigungsfunktion in ListView implementieren
View:
<ListView ItemsSource="{Binding Items}">
ViewModel:
public ObservableCollection<Recording> Items { get; set; }
- ObservableCollection sendet nur Benachrichtigungen, wenn Items hinzugefügt/entfernt werden oder wenn die gesamte Liste aktualisiert wird;
- Wenn die Oberfläche benachrichtigt werden soll, wenn sich der Inhalt eines Items (Recording) ändert, muss Recording INotifyPropertyChanged implementieren.
7. (View) Item-Vorlage (DataTemplate | UserControl) der ListView
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
{
return this._recording.A;
}
set
{
this._recording.A = value;
Notify(nameof(A));
}
}
public string B { get; set; } = this._recording.B;
public RecordingViewModel (Recording recording)
{
this._recording = recording;
}
}
Model:
public class Recording
{
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
... ...
}
Vergleich:

7.2. UserControl
7.2.1. DependencyProperty
- Übersicht über Abhängigkeitseigenschaften
- Nur DependencyProperty kann an andere Properties gebunden werden; nur eine Bindung kann Benachrichtigungen an die View implementieren
- Hat eine Priorität
View:
<control:MyControl Text="App wird durchsucht" IsSearching="{Binding ViewModel.IsSearching}" />
ViewModel:
public class MyControl
{
...
public static readonly DependencyProperty IsSearchingProperty =
DependencyProperty.Register
(
"IsSearching", typeof(Boolean),
typeof(MyControl), null
);
public bool IsSearching
{
get { return (bool)GetValue(IsSearchingProperty); }
set { SetValue(IsSearchingProperty, value); }
}
...
}
8. (ViewModel und Model) Datenkonvertierung – IValueConverter
Sie können IValueConverter verwenden, um Daten zwischen ViewModel und Model zu konvertieren.
public class ShowAllButtonVisibilityConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is IList)
{
int count = (value as IList).Count;
if (count > 3)
{
return Windows.UI.Xaml.Visibility.Visible;
}
}
return Windows.UI.Xaml.Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
if (value is IList)
{
int count = (value as IList).Count;
if (count > 3)
{
return Windows.UI.Xaml.Visibility.Visible;
}
}
return Windows.UI.Xaml.Visibility.Collapsed;
}
9. (View) Style des Controls ändern
9.1. Style im Control anpassen
View:
<TextBlock Foreground="Red" Text="SampleText" />
9.2. Einheitlichen Style verwenden – 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. ThemeResource verwenden
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. Panel verwenden
10.1. Grid
Merkmale:
- Standard Height/Width entspricht dem übergeordneten Element;
Empfehlung:
- Definieren Sie die Layoutgröße von untergeordneten Elementen in Grid;
- Proportionale Anzeige;
10.2. StackPanel
Merkmale:
- Kann die Grenzen des übergeordneten Elements überschreiten;
- Height oder Width ändern sich mit den Elementen im Panel;
Empfehlung:
- Verwenden Sie Padding und Proportionen flexibel;
- Geben Sie dem Width- oder Height-Wert von StackPanel im übergeordneten Element einen Wert, um zu verhindern, dass Controls ausufern;
11. (View) Adaptive UI (Adaptive UI)
- Verwenden Sie 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-Prinzipien
- Keine explizite Festlegung der Elementgröße;
- Keine Verwendung von Bildschirmkoordinaten zur Positionierung von Elementen;
- Untergeordnete Elemente im Container teilen sich den verfügbaren Platz;
- Verschachtelbare Layout-Container;
13. Lokalisierung (Localization)
- Verwenden Sie x:Uid, den eindeutigen Bezeichner des Elements
<TextBlock x:Uid="S_TextBlock1" />
- Verwenden Sie Ressourcendateien (Resources File)
<data name="S_TextBlock1.Text" xml:space="preserve">
<value>Beispieltext</value>
</data>
14. Namenskonventionen
Großer Camel-Case (PascalCase): firstName
Kleiner Camel-Case (camelCase): FirstName
- Class: Großer Camel-Case
- Property: Großer Camel-Case
- Field: Kleiner Camel-Case mit Präfix “_”
- Control in Xaml: Kleiner Camel-Case
15. Hinweise
- Benennen Sie Properties im ViewModel vorsichtig um, da die Binding-Namen in Xaml dem Refactoring nicht folgen;