Kolumne XAML Expertise: WPF und Windows-Apps

XAML-Tipp: WPF: Responsive Design – Automatisch die richtige Darstellung
Kommentare

In der Kolumne „XAML Expertise“ präsentiert Gregor Biswanger Top-How-tos zum Thema XAML. Einsteiger und fortgeschrittene XAML-Experten sollen hier durch geballtes Wissen gesättigt werden. Heute gibt es folgende Expertise: „WPF: Responsive Design – Automatisch die richtige Darstellung“.

Seit 2011 hat sich bei der Webentwicklung eine ganz neue Art von Design etabliert: Responsive Webdesign. Die Webseiten passen ihren Inhalt automatisch an die Browserfenstergröße an. Das hat den Effekt, dass auf einem Desktopgerät der verfügbare Platz für die Oberfläche komplett ausgereizt wird. Beim Öffnen einer Webseite auf dem Smartphone wird diese wie eine Art App optimiert dargestellt. Das Menü wird nicht komplett angezeigt, und nur relevanter Inhalt kommt zum Vorschein. Ein gutes Beispiel dafür ist www.daserste.de.

WPF: Responsive Design – Automatisch die richtige Darstellung

Vor dem Jahr 2011 gab es ebenfalls eine Lösung, die mit erheblichem Zeitaufwand verbunden war: Adaptive Webdesign. Beim Aufrufen einer Webseite wird dem Webserver übermittelt, ob es sich hierbei um einen mobilen oder einen Desktopbrowser handelt. Passend zur Anfrage wurde dann ein komplett eigenständiger Inhalt übermittelt. Der Nachteil war der doppelte Aufwand für Entwickler, und die mobile Version war auch nur für bestimmte Gerätegrößen brauchbar. Ein gutes Beispiel dafür ist www.lingscars.com.

Angelehnt an Adaptive Design und Responsive Design hat Microsoft für Universal Windows Apps ähnliche Lösungen integriert. So können für unterschiedliche Gerätegrößen unterschiedliche Visual States hinterlegt werden, und es gibt ganz neue Layoutsteuerelemente.

Für WPF hingegen bietet Microsoft bedauerlicherweise keine Lösung an. Schließlich soll eine WPF-Anwendung nur auf einem Desktop ausgeführt werden. Allerdings ist es aus Usability-Sicht sinnvoll, wie Microsoft-Produkte selbst beweisen. Dafür dient Microsoft Outlook 2017 als ideales Vorzeigebeispiel. Im Vollbild werden links alle Postfächer und Favoriten komplett angezeigt. Wird das Fenster hingegen kleiner, wird dieser Bereich automatisch zusammengeklappt. Auch wenn Microsoft keine integrierte WPF-Lösung für Responsive Design bieten möchte, zeigt dieses How-to, wie man mit nur wenigen Schritten zu diesem Komfort gelangen kann.

In der Webentwicklung wird für Responsive Design häufig ein Framework wie zum Beispiel Twitter Bootstrap eingesetzt. Dieses hat ein äußeres Layoutsteuerelement, das Container genannt wird und vergleichbar mit dem Grid-Steuerelement ist. Wird die Breite für eine Spalte zu klein, verschachtelt sich diese automatisch auf eine neue Zeile. Genau das möchten wir in WPF ebenfalls erreichen. Dazu wird beispielsweise ein Grid in zwei Spalten und zwei Zeilen angelegt. In der ersten Spalte und Zeile befindet sich unser Menü, in der zweiten Spalte der ersten Zeile ein einfaches Eingabefeld. Für dieses Eingabefeld mit Überschrift wird ein StackPanel eingesetzt. Dieses erhält einen Style, das einen DataTrigger bekommt. Der Trigger soll auf die Fenstergröße reagieren. Listing 1 zeigt den gesamten XAML-Code, der dazu nötigt ist.

Zum Auswerten der Fenstergröße wird ein eigener Value Converter namens IsValueLessThanParameter geschrieben. Dieser gibt in einem Boole-Wert zurück, ob das Fenster kleiner als eine vorgegebene Größe ist. Sollte das der Fall sein, triggert der DataTrigger einen Style an das StackPanel, das dieses nun in die erste Spalte der zweiten Zeile springen soll. Das war es auch schon. Der Code des IsValueLessThanParameter Value Converter steht in Listing 2.

Mit nur wenigen Zeilen Code und einem eigenen ValueConverter konnten wir unsere WPF-Anwendung um die Responsive-Design-Funktionalität erweitern. Abbildungen 1 und 2 zeigen, wie die Anwendung jetzt auf Größenänderungen reagiert.

Abb. 1: Die WPF-Anwendung im größeren Fenster

Abb. 1: Die WPF-Anwendung im größeren Fenster

Abb. 2: Die WPF-Anwendung reagiert automatisch auf Verkleinerung der Fenstergröße

Abb. 2: Die WPF-Anwendung reagiert automatisch auf Verkleinerung der Fenstergröße

Anhand dieser Vorgehensweise können noch viele weitere Responsive-Design-Patterns wie beispielsweise das Ausblenden von unnötigem Inhalt implementiert werden, falls der Platz zu eng wird.

<Window x:Name="window" x:Class="WpfResponsiveUI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfResponsiveUI"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="600">
  <Window.Resources>
    <local:IsValueLessThanParameter x:Key="IsValueLessThanParameter"/>
    <Style x:Key="ResponsiveLayoutStyle">
      <Setter Property="Grid.Column" Value="1" />
      <Setter Property="Grid.Row" Value="0" />
      <Style.Triggers>
        <DataTrigger Value="true" Binding="{Binding ActualWidth, ConverterParameter=400, Converter={StaticResource IsValueLessThanParameter}, ElementName=window, Mode=OneWay}">
          <Setter Property="Grid.Column" Value="0" />
          <Setter Property="Grid.Row" Value="1" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="100"/>
      <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="200"/>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Button Height="40" Margin="20">MENÜ</Button>

    <StackPanel Style="{StaticResource ResponsiveLayoutStyle}" Margin="0,0,0,0.5" Grid.RowSpan="2">
      <TextBlock Margin="20,20,20, 0">Name:</TextBlock>
      <TextBox Margin="20, 0, 20, 0"></TextBox>
    </StackPanel>
  </Grid>
</Window>
public class IsValueLessThanParameter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    double actualWidth = (Double) value;

    if (actualWidth < Int32.Parse((string)parameter))
    {
      return true;
    }

    return false;
  }

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

Windows Developer

Windows DeveloperDieser Artikel ist im Windows Developer erschienen. Windows Developer informiert umfassend und herstellerneutral über neue Trends und Möglichkeiten der Software- und Systementwicklung rund um Microsoft-Technologien.

Natürlich können Sie den Windows Developer über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist der Windows Developer ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -