Georg fährt extra nach Berlin um Steve Ballmer zu treffen

31 Tage Mango | Tag #15: Die ProgressBar

Die­ser Arti­kel ist Tag #15 der Serie 31 Tage Man­go von Jeff Blan­ken­burg.

Der Ori­gi­nal­ar­ti­kel befin­det sich hier: Day #15: The Pro­gress Bar.

Die­ser Arti­kel wur­de in der Ori­gi­nal­se­rie von Gast­au­tor Doug Mair geschrie­ben. Bei Twit­ter kann Doug unter @doug_mair erreicht wer­den.

Wenn Ihre Anwen­dung eine etwas län­ger dau­ern­de Ope­ra­ti­on durch­führt, ist es eine gute Idee, den Anwen­der über den Fort­schritt der Ope­ra­ti­on zu infor­mie­ren. Damit weiß der Anwen­der, dass die Anwen­dung noch beschäf­tigt ist und sich nicht auf­ge­hängt hat.

Wie kön­nen Sie den Anwen­der wis­sen las­sen, was gera­de pas­siert? Sie kön­nen bei­spiels­wei­se einen Text anzei­gen mit der Anzahl von her­un­ter­ge­la­de­nen Bytes oder der ver­blei­ben­den Dau­er für eine Ope­ra­ti­on. Oft sind Ihre Anwen­der aber gar nicht an so vie­len Details inter­es­siert. Fort­schritts­an­zei­gen („Pro­gress­Bar“) sind eine her­vor­ra­gen­de Mög­lich­keit, dem Anwen­der Akti­vi­tät anzu­zei­gen, ohne ihn mit detail­lier­ten Infor­ma­tio­nen zu über­häu­fen. Eine Pro­gress­Bar kann Akti­vi­tät in zwei ver­schie­de­nen Modi anzei­gen: im Inde­ter­mi­na­te Modus (unbestimmte/unbekannte Dau­er) und im Deter­mi­na­te Modus (fest­ge­leg­te obe­re Gren­ze des Fort­schritts).

Indeterminate Mode

Den Inde­ter­mi­na­te Mode ver­wen­den Sie, wenn Sie nicht wis­sen, wie lang die Ope­ra­ti­on dau­ern wird. Wenn Sie bei­spiels­wei­se mit einem Ser­ver ver­bin­den, wis­sen Sie nicht, wie lang das dau­ert (und ob die Ope­ra­ti­on über­haupt erfolg­reich sein wird). Pro­gress­Bars im Inde­ter­mi­na­te Mode zei­gen ihren Sta­tus durch klei­ne Punk­te, die in einer Ani­ma­ti­on von links nach rechts wan­dern. Sie zei­gen nur an, dass etwas pas­siert, geben dem Anwen­der aber kei­ne Hin­wei­se auf die ver­blei­ben­de Dau­er der Ope­ra­ti­on. Um eine Pro­gress­Bar in den Inde­ter­mi­na­te Mode zu ver­set­zen, set­zen Sie die Eigen­schaft IsIn­de­ter­mi­na­te auf true.

Determinate Mode

Wenn Sie (unge­fähr) wis­sen wie lang die Ope­ra­ti­on dau­ern wird, kön­nen Sie den Deter­mi­na­te Mode ver­wen­den. Damit kön­nen Sie dem Anwen­der den Fort­schritt in Pro­zent anzei­gen. Wenn Sie bei­spiels­wei­se eine Datei her­un­ter­la­den und die Gesamt­grö­ße der Datei ken­nen und wäh­rend des Down­loads wis­sen, wie­vie­le Bytes bereits her­un­ter­ge­la­den wur­den, kön­nen Sie dies für die Fort­schritts­an­zei­ge nut­zen.

Sie kön­nen die Gesamt­grö­ße der Datei durch die Anzahl der bereits her­un­ter­ge­la­de­nen Bytes tei­len um eine Pro­zent­an­ga­be für den Fort­schritt zu ermit­teln. Das fol­gen­de Bei­spiel zeigt, wie das aus­se­hen könn­te.

progressBar1.Value = (float)bytesRead / TotalFileSize;

Die­se Pro­zent­an­ga­be wird in der Pro­gress­Bar als Linie ange­zeigt. Um den Deter­mi­na­te Mode der Pro­gress­Bar zu akti­vie­ren, set­zen Sie die Eigen­schaft IsIn­de­ter­mi­na­te auf fal­se. Wei­ter­hin müs­sen Sie den Wert der Eigen­schaft Value set­zen um den aktu­el­len Fort­schritt in Pro­zent dar­zu­stel­len.

Seit Win­dows Pho­ne 7.5 Man­go gibt es neben dem ein­fa­chen Pro­gress­Bar Con­trol eine wei­te­re Mög­lich­keit der Fort­schritts­an­zei­ge:

  1. Pro­gress­Bar — Die­ses Con­trol kön­nen Sie belie­big (und mehr­fach) in Ihrer Sil­ver­light Page ver­wen­den.
  2. Pro­gress­In­di­ca­tor — Die­ses Con­trol ist fest oben in der Sys­tem Tray ver­an­kert.

Wen­den wir uns zunächst der Pro­gress­Bar zu.

ProgressBar

Die Pro­gress­Bar ist stan­dard­mä­ßig nicht in der Visu­al Stu­dio Tool­Box. Um sie hin­zu­zu­fü­gen, kli­cken wir mit rechts auf die Tool­box und wäh­len „Choo­se Items…“. Dann suchen wir „Pro­gress­Bar“ und machen einen Haken bei der ent­spre­chen­den Check­box.

Nach einer kur­zen Wei­le soll­ten Sie die „Pro­gress­Bar“ in der Tool­box sehen.

Jetzt kön­nen Sie das Pro­gress­Bar Con­trol auf Ihre XAML Sei­te zie­hen. Dadurch wird der XAML Sei­te der fol­gen­de Code hin­zu­ge­fügt.

<ProgressBar Name="progressBar1" Value="0"></ProgressBar>

Die Eigen­schaf­ten des Con­trols kön­nen Sie je nach Bedarf anpas­sen.

Um die Pro­gress­Bar im Deter­mi­na­te Mode zu ver­wen­den, müs­sen Sie sicher gehen, dass die Check­box IsIn­de­ter­mi­na­te nicht gecheckt ist. Mit den Wer­ten Mini­mum und Maxi­mum bestim­men Sie den Wer­te­be­reich der Fort­schritts­an­zei­ge und mit Value den aktu­el­len Wert.

Wäh­rend Ihre Ope­ra­ti­on Fort­schritt macht, set­zen Sie im code-behind den Wert von Value auf einen ent­spre­chen­den Wert zwi­schen Mini­mum und Maxi­mum. Wenn Sie Value auf einen Wert außer­hab der Gren­zen von Mini­mum und Maxi­mum set­zen, wird die Pro­gress­bar ein­fach 0 oder 100 Pro­zent anzei­gen.

ProgressIndicator

Der zwei­te Weg zur Fort­schritts­an­zei­ge ist über den Pro­gress­In­di­ca­tor. Die­ses Con­trol wird in der Sys­tem Tray ange­zeigt, so wie unten zu erken­nen. Das ers­te Bild zeigt die Sys­tem Tray im „Nor­mal­zu­stand“. Das zwei­te Bild zeigt die ein­ge­blen­de­te Pro­gress­Bar.

Um den Pro­gress­In­di­ca­tor zu ver­wen­den, fügen Sie das fol­gen­de using State­ment in der code-behind Datei hin­zu.

using Microsoft.Phone.Shell; 

Den eigent­li­chen Pro­gress­In­di­ca­tor anle­gen und der Sys­tem Tray hin­zu­fü­gen kön­nen Sie dann etwa so:

ProgressIndicator progressIndicator = new ProgressIndicator() {

IsVisible = true, IsIndeterminate = false,

Text = "Downloading file ..." };

SystemTray.SetProgressIndicator(this, progressIndicator);

Ach­ten Sie dar­auf, dass die Eigen­schaft Value des Pro­gress­In­di­ca­tor immer zwi­schen 0 und 1 sein muss. Hier haben Sie nicht die Mög­lich­keit, eige­ne Gren­zen mit Mini­mum und Maxi­mum anzu­ge­ben.

Beispielanwendung

In unse­rer Bei­spiel­an­wen­dung „Day15-Pro­gress­Bar“ wol­len wir bei­de Con­trols aus­pro­bie­ren:

Im XAML unten haben wir alle not­wen­di­gen Con­trols defi­niert: Es gibt eine Pro­gress­Bar, zwei But­tons, um einen Timer zu star­ten und anzu­hal­ten (die­ser wird unse­re Ope­ra­ti­on simu­lie­ren), und einen Sli­der, mit wel­chem wir den Wert des Pro­gress­In­di­ca­tor ver­än­dern kön­nen.

<phone:PhoneApplicationPage
  x:Class="Day15_ProgressBar.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
  FontFamily="{StaticResource PhoneFontFamilyNormal}"
  FontSize="{StaticResource PhoneFontSizeNormal}"
  Foreground="{StaticResource PhoneForegroundBrush}"
  SupportedOrientations="Portrait" Orientation="Portrait"
  shell:SystemTray.IsVisible="True">

  <!--LayoutRoot is the root grid where all page content is placed-->

  <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    
    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
      <TextBlock x:Name="ApplicationTitle" Text="DAY 15" Style="{StaticResource PhoneTextNormalStyle}"/>
      <TextBlock x:Name="PageTitle" Text="making progress" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" FontSize="56" />
    </StackPanel>

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
      <StackPanel>
        <TextBlock FontSize="36" Foreground="#FFDBE6FF" Name="textBlock3" Text="Progress Indicator" TextWrapping="Wrap" FontWeight="Bold" />
        <TextBlock Name="textBlock1" Text="Drag the Slider to see the Progess In System Tray." FontSize="20" TextWrapping="Wrap" Foreground="#FFDBE6FF" />
        <Slider Name="slider1" Width="Auto" Maximum="1" LargeChange="0.1" SmallChange="0.01" ValueChanged="slider1_ValueChanged" Margin="50,0" />
        <TextBlock FontSize="36" Name="textBlock2" Text="Progress Bar" TextWrapping="Wrap" Foreground="#FFDBE6FF" Margin="0,50,0,0" FontWeight="Bold" />
        <Button Name="StartButton" Content="Start the Timer" Click="Button_Click"></Button>
        <Button Name ="StopButton" Content="Reset the Timer" Click="Button_Click_1"></Button>
        <ProgressBar Name="progressBar1" Value="0" IsIndeterminate="False" Height="50" SmallChange=".5" LargeChange="10"></ProgressBar>
      </StackPanel>
    </Grid>
  </Grid>
</phone:PhoneApplicationPage>

Nach dem XAML Code für die Benut­zer­ober­flä­che las­sen Sie uns den C# code-behind anschau­en.

Zunächst fügen wir eini­ge using State­ments ein für die Con­trols, die wir ver­wen­den wer­den. Für den Pro­gress­In­di­ca­tor nut­zen wir den Name­space Microsoft.Phone.Shell. Inner­halb der Klas­se defi­nie­ren wir eini­ge Varia­blen. Wir erstel­len einen Pro­gress­In­di­ca­tor, den wir spä­ter in die Sys­tem­Tray hän­gen wer­den. Ein Dispatcher­Ti­mer erstel­len wir, um eine län­ger dau­ern­de Ope­ra­ti­on zu simu­lie­ren. Im Kon­struk­tur hän­gen wir das Objekt pro­gress­In­di­ca­tor in die Sys­tem­Tray und initia­li­sie­ren den Timer, so dass er die Metho­de timer_Tick alle 5000 Ticks auf­ruft.

using System;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Phone.Shell;

namespace Day15_ProgressBar
{
   public partial class MainPage
   {
      ProgressIndicator progressIndicator = new ProgressIndicator() { IsVisible = true, IsIndeterminate = false, Text = "Downloading file ..." };

      DispatcherTimer timer = new DispatcherTimer();

      // Constructor
      public MainPage()
      {
         InitializeComponent();

         SystemTray.SetProgressIndicator(this, progressIndicator);

         timer = new DispatcherTimer {Interval = new TimeSpan(5000)};
         timer.Tick += timer_Tick;
         timer.Stop();
      }
   }
}

Jedes Mal, wenn der Timer feu­ert und damit die Metho­de timer_Tick auf­ge­ru­fen wird, erhö­hen wir den Wert der Eigen­schaft Value der pro­gress­Bar. Dadurch macht es den Anschein, als mache unse­re simu­lier­te Ope­ra­ti­on Fort­schritt.

Feh­len noch die Metho­den für die But­ton Click Events. Die­se star­ten und stop­pen den Timer — sie star­ten und been­den also unse­re lang dau­ern­de Ope­ra­ti­on. Wenn man den Start But­ton drückt, wird der Wert der Eigen­schaft Value der pro­gress­Bar auf 0 zurück­ge­setzt und der Timer gestar­tet. Der Stop But­ton setzt eben­falls den Wert auf 0 und hält den Timer an.

Die letz­te ver­blie­be­ne Metho­de ist der Event Hand­ler slider1_ValueChanged, die auf­ge­ru­fen wird, wenn der Anwen­der den Sli­der bewegt. Die Posi­ti­on des Sli­ders wer­den wir ver­wen­den, um den Wert des Pro­gress­In­di­ca­tor zu set­zen.

using System;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Phone.Shell;

namespace Day15_ProgressBar
{
   public partial class MainPage
   {
      // Constructor
      ProgressIndicator progressIndicator = new ProgressIndicator() { IsVisible = true, IsIndeterminate = false, Text = "Downloading file ..." };

      DispatcherTimer timer = new DispatcherTimer();

      public MainPage()
      {
         InitializeComponent();

         SystemTray.SetProgressIndicator(this, progressIndicator);

         timer = new DispatcherTimer {Interval = new TimeSpan(5000)};
         timer.Tick += timer_Tick;
         timer.Stop();
      }

      void timer_Tick(object sender, EventArgs e)
      {
         progressBar1.Value += progressBar1.SmallChange;
      }

      private void Button_Click(object sender, RoutedEventArgs e)
      {
         progressBar1.Value = 0;
         timer.Start();
      }

      private void Button_Click_1(object sender, RoutedEventArgs e)
      {
         timer.Stop();
         progressBar1.Value = 0;
      }

      private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
      {
         progressIndicator.Value = e.NewValue;
      }
   }
}

Zusammenfassung

In die­sem Arti­kel haben Sie gese­hen, wie man die veschie­de­nen Fort­schritts­an­zei­gen in einer Win­dows Pho­ne Man­go Anwen­dung ver­wen­den kann. Mit weni­gen Zei­len Code kön­nen Sie kom­plet­te Fort­schritts­an­zei­gen zu einer Sil­ver­light Win­dows Pho­ne Anwen­dung hin­zu­fü­gen. Sie kön­nen ent­we­der einen Pro­gress­In­di­ca­tor erstel­len, der in der Sys­tem­Tray ange­zeigt wird, oder eine Pro­gress­Bar, die irgend­wo auf der Sei­te ange­zeigt wer­den kann.

Fort­schritts­an­zei­gen sind ein wesent­li­cher Bestand­teil von Anwen­dun­gen, die län­ge­re Ope­ra­tio­nen durch­füh­ren. Sie geben dem Anwen­der das Gefühl, dass die Anwen­dung noch am Leben ist und arbei­tet. Die Anwen­der füh­len sich woh­ler, wenn Sie über den Fort­schritt der Anwen­dung Bescheid wis­sen.

Um eine lauf­fä­hi­ge Ver­si­on der Anwen­dung die­ses Arti­kels her­un­ter­zu­la­den, drü­cken Sie auf den Down­load Code But­ton.

Mor­gen wer­den wir uns den Iso­la­ted Sto­rage Explo­rer anschau­en. Damit kön­nen Sie von Ihrer Anwen­dung im Emu­la­tor oder auf einem ech­ten Gerät gespei­cher­te Daten anse­hen und unter­su­chen. Sami­dip Basu wird Ihnen alles rund um die­ses neue Fea­ture erklä­ren.

Bis dahin!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert