Von statischen Inhalten bis hin zum Data Binding

Windows Phone-Programmierer können sich aussuchen, ob sie Inhalte einer Windows Phone-Page statisch oder dynamisch erstellen wollen. Eine statische Liste könnte beispielsweise so aussehen:

ListBox mit statischen Inhalten

MainPage.xaml

1
2
3
4
<ListBox>
  <TextBlock Text="Benny Neugebauer" />
  <TextBlock Text="Tamay Gündüz" />
</ListBox>

ListBox dynamisch befüllt, vom CodeBehind

Möchte man das Ganze etwas dynamischer haben, bietet es sich an, der ListBox einen Namen zu geben und über den CodeBehind anzusprechen und mit dynamisch generierten TextBlock-Elementen zu füllen:

MainPage.xaml

1
2
<ListBox x:Name="myListBox">
</ListBox>

MainPage.xaml.cs

1
2
3
4
5
6
7
8
9
10
public MainPage()
{
  InitializeComponent();
  //
  List<TextBlock> myList = new List<TextBlock>();
  TextBlock benny = new TextBlock { Text = "Benny Neugebauer" };
  TextBlock tamay = new TextBlock { Text = "Tamay Gündüz" };
  myListBox.Items.Add(benny);
  myListBox.Items.Add(tamay);
}

Der Nachteil dieser Methodik ist aber, dass im Quellcode (der eigentlich für die Logik gedacht ist) Design-Elemente (Textblöcke) erzeugt werden. Dadurch werden Design und Logik vermischt und nicht sauber getrennt. Doch dafür gibt es Abhilfe.

ListBox mit Data Binding

Die schönste Art und Weise seine View mit Daten zu füllen ist das Data Binding. Dazu braucht man eine ItemsSource, ein ItemTemplate und ein DataTemplate:

MainPage.xaml

1
2
3
4
5
6
7
<ListBox x:Name="myListBox" ItemsSource="{Binding}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding}" />
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

MainPage.xaml.cs

1
2
3
4
5
6
7
8
9
public MainPage()
{
  InitializeComponent();
  //
  List<string> myList = new List<string>();
  myList.Add("Benny Neugebauer");
  myList.Add("Tamay Gündüz");
  myListBox.DataContext = myList;
}

ListBox mit Data Binding und komplexem Datentyp

Wer noch schöner programmieren möchte, der erstellt einen eigenen Datentyp für die darzustellenden Elemente.

MainPage.xaml

1
2
3
4
5
6
7
<ListBox x:Name="myListBox" ItemsSource="{Binding}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding}" />
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Person.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace PhoneApp
{
  public class Person
  {
    public string FirstName { get; set; }
    public string LastName { get; set; }
 
    public override string ToString()
    {
      return FirstName+" "+LastName;
    }
  }
}

MainPage.xaml.cs

1
2
3
4
5
6
7
8
9
public MainPage()
{
  InitializeComponent();
  //
  List<Person> myList = new List<Person>();
  myList.Add(new Person { FirstName = "Benny", LastName = "Neugebauer" });
  myList.Add(new Person { FirstName = "Tamay", LastName = "Gündüz" });
  myListBox.DataContext = myList;
}

ListBox mit StackPanel, Data Binding und komplexem Datentyp

Um das Beispiel noch abzurunden, hier ein Beispiel mit etwas schönerer View und Binding von einzelnen Properties:

MainPage.xaml

1
2
3
4
5
6
7
8
9
10
11
12
13
<ListBox x:Name="myListBox" ItemsSource="{Binding}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Number}" Style="{StaticResource PhoneTextLargeStyle}" />
        <StackPanel Orientation="Vertical">
          <TextBlock Text="{Binding FirstName}" />
          <TextBlock Text="{Binding LastName}" />
        </StackPanel>
      </StackPanel>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

Person.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace PhoneApp
{
  public class Person
  {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Number { get; set; }
 
    public override string ToString()
    {
      return FirstName+" "+LastName;
    }
  }
}

MainPage.xaml.cs

1
2
3
4
5
6
7
8
9
public MainPage()
{
  InitializeComponent();
  //
  List<Person> myList = new List<Person>();
  myList.Add(new Person { FirstName = "Benny", LastName = "Neugebauer", Number = 1 });
  myList.Add(new Person { FirstName = "Tamay", LastName = "Gündüz", Number = 2 });
  myListBox.DataContext = myList;
}

Ergebnis

Vielen Dank an Tamay Gündüz für seine hilfreichen Kommentare. Wer übrigens seine Windows Phone Kenntnisse vertiefen möchte, sollte unbedingt Tamays Windows Phone Coding Camp vom 16. – 17. Juni in Hamburg besuchen oder in der Dark Side Bakery in Berlin vorbeischauen.

Hinweise

String-Template anstatt String-Konkatenation

Wer diese String-Konkatenation nicht sonderlich mag:

1
2
3
4
public override string ToString()
{
  return FirstName+" "+LastName;
}

Der kann auch ein String-Template verwenden:

1
2
3
4
public override string ToString()
{
  return String.Format("{0} {1}", FirstName, LastName);
}

Initialisierung von XAML-Komponenten

Damit vom CodeBehind auf die in XAML definierten Objekte (wie beispielsweise myListBox) zugreifen kann, müssen alle Operationen nach der Anweisung InitializeComponent(); ausgeführt werden. Wer wirklich hundertprozentig sicher gehen möchte, dass alle XAML-Objekte vollständig geladen sind, der sollte außerdem seinen Code nicht im Konstruktur, sondern in der OnNavigatedTo-Methode ausführen.

Beispiel:

1
2
3
4
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
  // Your code here...
}

XAML Code mit User Controls auslagern und wiederverwenden

XAML-Code wird oft für das Design der eigenen Windows Phone-Applikation verwendet. Wer bestimmte Design-Elemente wiederverwenden möchte, der kann XAML-Code auch auslagern und in mehreren Pages wiederverwenden. Wie das funktioniert, möchte ich an einem kurzen Beispiel erläutern.
XAML Code mit User Controls auslagern und wiederverwenden weiterlesen

LaTeX Formeln in XAML Code umwandeln

Wer Formeln mit LaTeX erstellt, möchte meist, dass diese Formeln vektorisiert dargestellt werden, um beliebig groß und scharf skaliert werden zu können. Zur Darstellung in Windows 8 oder auf einem Windows Phone bietet sich dazu XAML Code an, der Vektor-Pfade benutzt.

Ich möchte kurz aufführen, wie die Arbeitsschritte aussehen, um aus einer LaTeX Formel eine vektorbasierte XAML Datei zu erstellen.
LaTeX Formeln in XAML Code umwandeln weiterlesen

Auf XAML Elemente vom Code-Behind zugreifen

Die Inhalte von XAML-Elementen können fest im XAML-Code gesetzt werden:

MainPage.xaml

1
2
3
<controls:Pivot Title="Hello World">
  <controls:PivotItem Header="Item 1"></controls:PivotItem>
</controls:Pivot>

Man kann aber den XAML-Elementen auch Namen zuweisen und dann vom Code-Behind drauf zugreifen:

MainPage.xaml

1
2
<controls:Pivot x:Name="MyPivotList" Title="Hello World">
</controls:Pivot>

MainPage.xaml.cs

1
2
3
4
5
6
7
8
9
10
11
12
public MainPage()
{
  InitializeComponent();
 
  TextBlock NewTextBlock = new TextBlock();
  NewTextBlock.Text = "Item 1";
 
  PivotItem NewPivotItem = new PivotItem();
  NewPivotItem.Header = NewTextBlock;
 
  MyPivotList.Items.Add(NewPivotItem);
}

Assembly Microsoft.Phone.Controls verwenden

Um tolle Windows Phone UI-Elemente, wie etwa das Pivot-Element, benutzen zu können, muss der Microsoft.Phone.Controls Namespace deklariert werden. Dazu muss man seinem Projekt einen Verweis auf die „Windows Phone Controls“-Assembly (Bibliothek) hinzufügen (Verweis hinzufügen -> .NET -> Microsoft.Phone.Controls):

Achtung: Der Verweis kann nur hinzugefügt werden, wenn das Silverlight for Windows Phone Toolkit installiert ist. Ob das Toolkit bereits installiert ist, erkennt man daran, ob ein Ordner namens Toolkit im Windows Phone SDK-Installationsort (z.B. C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.1) vorhanden ist.

Sobald der Verweis vorhanden ist, kann man den Namespace in seiner XAML-Datei (z.B. MainPage.xaml) einbinden:

1
2
3
4
5
<phone:PhoneApplicationPage 
    ...
    xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
    ...
>

Durch den Namespace controls stehen dann einem erweiterte Deklarationsmöglichkeiten zur Verfügungen, mit denen sich beispielsweise eine Pivot-Ansicht erstellen lässt:

1
2
3
4
5
6
7
8
<controls:Pivot Title="PIVOT DEMONSTRATION">
    <controls:PivotItem Header="Item 1">
    </controls:PivotItem>
    <controls:PivotItem Header="Item 2">
    </controls:PivotItem>
    <controls:PivotItem Header="Item 3">
    </controls:PivotItem>
</controls:Pivot>

Hello World-App mit Windows Phone und Android

Aus Jux und Dollerei habe ich eine native Hello World-App für Windows Phone und Android gebaut, welche bei Klick auf einen Button ein Pop-Up anzeigt. Bei der Entwicklung des Beispiels war es mir wichtig, ein ähnliches und überschaubares Projekt mit Android-Code (Java) und Windows Phone-Code (C#) zu entwerfen, welches die Ähnlichkeiten und Unterscheide beider Programmiersprachen zeigt.

Hier der Code für meinem Vergleich:
Hello World-App mit Windows Phone und Android weiterlesen