## 19.10 Weitere Steuerelemente ### 19.10.1 Die »ProgressBar« Das Element ProgressBar dient dazu, den Benutzer bei einer lange andauernden Verarbeitung über den aktuellen Fortschritt zu informieren. Die wichtigsten Eigenschaften sind schnell genannt: Minimum beschreibt den Minimalwert, die Eigenschaft Maximum den Maximalwert, und Value bestimmt die aktuelle Position.
    <ProgressBar Minimum="0" Maximum="100" Value="35" Height="25"/>
Eine interessante Eigenschaft der ProgressBar soll aber nicht unerwähnt bleiben: IsIndeterminate. Sie können diese Eigenschaft auf True festlegen, wenn die aktuelle Fortschrittsposition nicht festzustellen bzw. unbekannt ist. In diesem Fall werden die drei Eigenschaften Minimum, Maximum und Value ignoriert, und stattdessen wird anstelle des Fortschrittsbalkens eine Animation angezeigt. ### 19.10.2 Das Steuerelement »Slider« Mit dem Slider-Steuerelement kann der Anwender einen bestimmten Wert einstellen. Zur Festlegung des minimalen und maximalen Werts dienen auch hier die Eigenschaften Minmum und Maximum, und die Eigenschaft Value beschreibt den aktuellen Wert. Mit der Eigenschaft TickFrequency können Sie eine Hilfsskala einblenden, die mit TickPlacement am Slider ausgerichtet werden kann. Der an TickFrequency zugewiesene Wert beschreibt den Abstand der Hilfslinien. Mit der Eigenschaft IsSnapToTickEnabled=True bewirken Sie, dass der Anwender nicht einen beliebigen Wert einstellen kann, sondern nur Werte, die durch die Hilfslinien vorgegeben werden. Der Schieberegler schnappt also ein.
    <Slider TickFrequency="5" TickPlacement="BottomRight" Minimum="0"
            Maximum="100" IsSnapToTickEnabled="True"></Slider>
Hier klicken, um das Bild zu vergrößern Abbildung 19.32 Das Slider-Steuerelement Normalerweise wird der Minimalwert links und der Maximalwert rechts ausgerichtet. Mit IsDirectionReversed kann die Ausrichtung umgekehrt werden. Klickt der Anwender links oder rechts vom Schieberegler, wird zum aktuellen Wert der unter LargeChange eingestellte Wert addiert bzw. von ihm subtrahiert. Soll stattdessen die exakte Klickposition zur Festlegung des neuen Wertes herangezogen werden, ist die Eigenschaft IsMoveToPointEnabled auf True einzustellen. ### 19.10.3 Das »GroupBox«-Steuerelement Bei der GroupBox handelt es sich um ein Steuerelement, das mehrere andere Steuerelemente visuell zusammenfassen kann. Der von einer GroupBox einfasste Inhalt wird durch die Eigenschaft Content beschrieben. Dabei kann es sich um einen LayoutContainer handeln, sodass im Grunde genommen beliebig viele Elemente einer GroupBox zugeordnet werden können. Eine GroupBox kann eine Beschriftung aufweisen. Dazu dient die Eigenschaft Header. Natürlich kann Header auch ein anderes Steuerelement beschreiben. Der folgende XAML-Code beschreibt zwei GroupBox-Elemente. Das untere weist ein CheckBox-Element in der Eigenschaft Header auf.
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition /><RowDefinition />
      </Grid.RowDefinitions>
      <GroupBox Grid.Row="0" Header="Schriftstil" BorderThickness="2"
                                                  BorderBrush="Black">
        <StackPanel>
          <CheckBox>Fett</CheckBox>
          <CheckBox>Kursiv</CheckBox>
          <CheckBox>Unterstrichen</CheckBox>
        </StackPanel>
      </GroupBox>
      <GroupBox Grid.Row="1" BorderThickness="2" BorderBrush="Black">
        <GroupBox.Header>
          <CheckBox>Aktivierung</CheckBox>
        </GroupBox.Header>
        <StackPanel>
          <TextBox Margin="5"></TextBox>
          <TextBox Margin="5"></TextBox>
        </StackPanel>
      </GroupBox>
    </Grid>
Hier klicken, um das Bild zu vergrößern Abbildung 19.33 Zwei GroupBox-Steuerelemente ### 19.10.4 Das Steuerelement »ScrollViewer« Einige WPF-Steuerelemente sind zwar in der Lage, einen umfangreichen Inhalt anzuzeigen, unterstützen aber leider keine Scrollbars. Dieses Manko kann durch das Steuerelement ScrollViewer behoben werden. Ein ScrollViewer zeigt Scrollbars an, sobald der Inhalt eines Elements größer wird als sein Anzeigebereich und die beiden Eigenschaften HorizontalScrollBarVisibility und VerticalScrollBarVisibility auf Visible eingestellt sind. Eine Reihe von Methoden ermöglichen es, den angezeigten Inhalt beliebig zu verschieben, z. B. ScrollToLeftEnd oder LineRight. Um die Wirkungsweise der Methoden einfach zu erfahren, dient das folgende Beispielprogramm. Für die infrage kommenden Methoden sind linksseitig Buttons angeordnet. Die Methode, die von dem jeweiligen Button aufgerufen wird, ist in der Beschriftung angegeben. Der XAML- und C#-Code wird an dieser Stelle aus Platzgründen nur gekürzt wiedergegeben.
    // ------------------------------------------------------------------
    // Beispiel: ...\Kapitel 19\ScrollViewerSample
    // -----------------------------------------------------------------.
    <DockPanel>
      <StackPanel DockPanel.Dock="Left" Orientation="Vertical" Width="120"
                  ButtonBase.Click="ButtonHandler" >
        <Button Name="btnLineUp" Margin="5,5,5,5" Content="LineUp()" />
        <Button Name="btnLineDown" Margin="5,5,5,5" Content="LineDown()" />
        <Button Name="btnLineRight" Margin="5,5,5,5" Content="LineRight()" />
        <Button Name="btnLineLeft" Margin="5,5,5,5" Content="LineLeft()" />
        ...
      </StackPanel>
      <ScrollViewer Name="scrViewer" Margin="5"
                    HorizontalScrollBarVisibility="Visible"
                    VerticalScrollBarVisibility="Visible">
        <TextBlock Margin="10" TextWrapping="Wrap" Width="500">
          ...
        </TextBlock>
      </ScrollViewer>
    </DockPanel>
Zu diesem XAML-Code gehört der folgende C#-Code:
    private void ButtonHandler(object sender, RoutedEventArgs e) {
      Button btn = e.Source as Button;
      switch (btn.Name) {
        case "btnLineUp":
          scrViewer.LineUp();
          break;
        case "btnLineDown":
          scrViewer.LineDown();
          break;
        case "btnLineRight":
          scrViewer.LineRight();
          break;
        ...
      }
    }
Hier klicken, um das Bild zu vergrößern Abbildung 19.34 Ausgabe des Beispielprogramms »ScrollViewerSample« ### 19.10.5 Das Steuerelement »Expander« Das Steuerelement Expander ist der Gruppe der Steuerelemente zuzurechnen, die dem Design dienen. Das Element kann ein untergeordnetes Element beinhalten. Der Bereich, der von dem untergeordneten Steuerelement beschrieben wird, kann aufgeklappt oder zusammengeklappt dargestellt werden. Im zusammengeklappten Zustand wird lediglich ein Pfeil angezeigt, über den der verdeckte Inhalt wieder sichtbar gemacht werden kann. Expander-Objekte eignen sich besonders dann, wenn ein Detailbereich für den Anwender eingeblendet werden soll. Der Zustand des Expander-Objekts wird mit der Eigenschaft IsExpanded beschrieben. Die Eigenschaft ExpandedDirection gibt die Richtung an, in die aufgeklappt wird. Dabei sind die Richtungen links, rechts, oben und unten möglich. Wird der Inhalt in vertikaler Richtung aufgeklappt, passt sich die Höhe des angezeigten Bereichs dem Inhalt an. Entsprechendes gilt, wenn in horizontaler Richtung aufgeklappt wird. Hier ist es natürlich die Breite, die sich dem Inhalt anpasst. Erwähnenswert ist, das beim Öffnen und Schließen des Expander-Objekts die Ereignisse Expanded und Collapsed ausgelöst werden. Sie können somit auf diese Aktionen auch mit entsprechenden Operationen reagieren.
    // ------------------------------------------------------------------
    // Beispiel: ...\Kapitel 19\ExpanderSample
    // -----------------------------------------------------------------.
    <StackPanel>
      <Expander Margin="10">
        <Expander.Background>
          <LinearGradientBrush StartPoint="0,0" EndPoint="1,2">
            <GradientStop Offset="0" Color="White" />
            <GradientStop Offset="1" Color="Blue" />
          </LinearGradientBrush>
        </Expander.Background>
        <StackPanel>
          <Button Height="30" Margin="5">Button 1</Button>
          <Button Height="30" Margin="5">Button 2</Button>
          <Button Height="30" Margin="5">Button 3</Button>
        </StackPanel>
      </Expander>
      <Expander Margin="10">
        <Expander.Background>
          <LinearGradientBrush StartPoint="0,0" EndPoint="1,2">
            <GradientStop Offset="0" Color="White" />
            <GradientStop Offset="1" Color="Red" />
          </LinearGradientBrush>
        </Expander.Background>
        <StackPanel>
          <Button Height="30" Margin="5">Button 4</Button>
          <Button Height="30" Margin="5">Button 5</Button>
          <Button Height="30" Margin="5">Button 6</Button>
        </StackPanel>
      </Expander>
    </StackPanel>
Hier klicken, um das Bild zu vergrößern Abbildung 19.35 Zwei Expander-Objekte (Das obere ist zusammengeklappt.) ### 19.10.6 Das Steuerelement »Border« Das Border-Steuerelement ist ein sehr einfaches Steuerelement, das dazu dient, einen visuellen Rahmen um andere Steuerelemente zu zeichnen. Border ist ein Inhaltssteuerelement. Das bedeutet, dass es direkt nur ein anderes Element beinhalten kann. Üblicherweise handelt es dabei um einen LayoutContainer. Nur wenige Eigenschaften sind erwähnenswert: Mit CornerRadius können die Ecken abgerundet werden, BorderThickness legt die Breite fest, und BorderBrush definiert das Aussehen des Rahmens.
    // ------------------------------------------------------------------
    // Beispiel: ...\Kapitel 19\BorderSample
    // -----------------------------------------------------------------.
    <Grid>
      <Border CornerRadius="20" BorderThickness="25" Margin="5">
        <Border.BorderBrush>
          <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
            <GradientStop Offset="0" Color="White" />
            <GradientStop Offset="1" Color="Blue" />
          </LinearGradientBrush>
        </Border.BorderBrush>
        <StackPanel>
          <Button Height="40" Margin="20, 20, 20, 10">Button 1</Button>
          <Button Height="40" Margin="20, 10, 20, 20">Button 2</Button>
        </StackPanel>
      </Border>
    </Grid>
Die Ausgabe dieses Beispiels sehen Sie in Abbildung 19.36. Hier klicken, um das Bild zu vergrößern Abbildung 19.36 Die Ausgabe des Beispiels »BorderSample« ### 19.10.7 Die »Image«-Komponente Mit dem Image-Control lassen sich Grafiken in einem Window anzeigen. Die wichtigste Eigenschaft ist Source. Dieser übergeben Sie den relativen oder absoluten Pfad einer Grafikdatei. Image ermöglicht die Anzeige der folgenden Bildtypen: .BMP, .GIF, .ICO, .JPG, .PNG, .WDP und .TIFF. Unterscheiden sich die Größe des Image-Controls und die der Grafik, können Sie mit den Eigenschaften Stretch und StretchDirection festlegen, wie die Grafik gestreckt werden soll. StretchDirection erlaubt die Werte Both, DownOnly und UpOnly. Mit DownOnly wird das Bild nur verkleinert dargestellt, mit UpOnly nur vergrößert, und Both ermöglicht beide Änderungen. Letzteres ist auch die Standardvorgabe. Ist Stretch auf None eingestellt, wird das Bild ausschließlich in seiner Originalgröße dargestellt. Mit Fill wird das Bild so skaliert, dass es den Bereich des Image-Steuerelements komplett einnimmt. UniFormFill agiert ähnlich, achtet aber darauf, dass die Proportionen erhalten bleiben. Leere Flächen innerhalb des Steuerelements verbleiben nicht. Uniform vergrößert oder verkleinert das Bild in der Weise, dass die Proportionen erhalten bleiben. Möglicherweise bleiben dabei aber wieder Flächen im Image-Steuerelement frei. Abbildung 19.37 zeigt, wie sich das Strecken eines Bildes auf die Darstellung auswirkt. Der Abbildung liegt der folgende Code zugrunde:
    <WrapPanel>
      <Image Source="Images/Egypt.JPG" Margin="10" Height="200" />
      <Image  Source="Images/Egypt.JPG" Margin="10" Height="200"
              Width="300" Stretch="Fill" />
    </WrapPanel>
Hier klicken, um das Bild zu vergrößern Abbildung 19.37 Bildanzeige normal und gestreckt ### 19.10.8 Grafik zur Laufzeit laden Wenn Sie mittels Code eine Bitmap laden, kommt die Klasse BitmapImage ins Spiel, die im Namespace System.Windows.Media.Imaging definiert ist. Der Ladevorgang wird zunächst mit der Methode BeginInit initialisiert und mit EndInit abgeschlossen. Das BitmapImage-Objekt erwartet in der Eigenschaft UriSource die Angabe der Datenquelle, die als Objekt vom Typ Uri übergeben wird. Dem Uri-Konstruktor übergeben Sie den Pfad zu der Bitmap, und Sie teilen ihm darüber hinaus mit, ob es sich um eine relative oder absolute Pfadangabe handelt. Der Code in der XAML-Datei lautet:
    <WrapPanel>
      <Image Name="MyImage" />
    </WrapPanel>
Das Bild soll beim Starten des Windows geladen werden. Dazu bietet sich das Ereignis Loaded an:
    private void Window_Loaded(object sender, RoutedEventArgs e) {
      BitmapImage bitmap = new BitmapImage();
      bitmap.BeginInit();
      bitmap.UriSource = new Uri("Images/Egypt.jpg", UriKind.Relative);
      bitmap.EndInit();
      MyImage.Source = bitmap;
    }