Dieser Artikel ist Tag #15 der Serie 31 Tage Mango von Jeff Blankenburg.
Der Originalartikel befindet sich hier: Day #15: The Progress Bar.
Dieser Artikel wurde in der Originalserie von Gastautor Doug Mair geschrieben. Bei Twitter kann Doug unter @doug_mair erreicht werden.
Wenn Ihre Anwendung eine etwas länger dauernde Operation durchführt, ist es eine gute Idee, den Anwender über den Fortschritt der Operation zu informieren. Damit weiß der Anwender, dass die Anwendung noch beschäftigt ist und sich nicht aufgehängt hat.
Wie können Sie den Anwender wissen lassen, was gerade passiert? Sie können beispielsweise einen Text anzeigen mit der Anzahl von heruntergeladenen Bytes oder der verbleibenden Dauer für eine Operation. Oft sind Ihre Anwender aber gar nicht an so vielen Details interessiert. Fortschrittsanzeigen („ProgressBar“) sind eine hervorragende Möglichkeit, dem Anwender Aktivität anzuzeigen, ohne ihn mit detaillierten Informationen zu überhäufen. Eine ProgressBar kann Aktivität in zwei verschiedenen Modi anzeigen: im Indeterminate Modus (unbestimmte/unbekannte Dauer) und im Determinate Modus (festgelegte obere Grenze des Fortschritts).
Indeterminate Mode
Den Indeterminate Mode verwenden Sie, wenn Sie nicht wissen, wie lang die Operation dauern wird. Wenn Sie beispielsweise mit einem Server verbinden, wissen Sie nicht, wie lang das dauert (und ob die Operation überhaupt erfolgreich sein wird). ProgressBars im Indeterminate Mode zeigen ihren Status durch kleine Punkte, die in einer Animation von links nach rechts wandern. Sie zeigen nur an, dass etwas passiert, geben dem Anwender aber keine Hinweise auf die verbleibende Dauer der Operation. Um eine ProgressBar in den Indeterminate Mode zu versetzen, setzen Sie die Eigenschaft IsIndeterminate auf true.
Determinate Mode
Wenn Sie (ungefähr) wissen wie lang die Operation dauern wird, können Sie den Determinate Mode verwenden. Damit können Sie dem Anwender den Fortschritt in Prozent anzeigen. Wenn Sie beispielsweise eine Datei herunterladen und die Gesamtgröße der Datei kennen und während des Downloads wissen, wieviele Bytes bereits heruntergeladen wurden, können Sie dies für die Fortschrittsanzeige nutzen.
Sie können die Gesamtgröße der Datei durch die Anzahl der bereits heruntergeladenen Bytes teilen um eine Prozentangabe für den Fortschritt zu ermitteln. Das folgende Beispiel zeigt, wie das aussehen könnte.
progressBar1.Value = (float)bytesRead / TotalFileSize;
Diese Prozentangabe wird in der ProgressBar als Linie angezeigt. Um den Determinate Mode der ProgressBar zu aktivieren, setzen Sie die Eigenschaft IsIndeterminate auf false. Weiterhin müssen Sie den Wert der Eigenschaft Value setzen um den aktuellen Fortschritt in Prozent darzustellen.
Seit Windows Phone 7.5 Mango gibt es neben dem einfachen ProgressBar Control eine weitere Möglichkeit der Fortschrittsanzeige:
- ProgressBar — Dieses Control können Sie beliebig (und mehrfach) in Ihrer Silverlight Page verwenden.
- ProgressIndicator — Dieses Control ist fest oben in der System Tray verankert.
Wenden wir uns zunächst der ProgressBar zu.
ProgressBar
Die ProgressBar ist standardmäßig nicht in der Visual Studio ToolBox. Um sie hinzuzufügen, klicken wir mit rechts auf die Toolbox und wählen „Choose Items…“. Dann suchen wir „ProgressBar“ und machen einen Haken bei der entsprechenden Checkbox.
Nach einer kurzen Weile sollten Sie die „ProgressBar“ in der Toolbox sehen.
Jetzt können Sie das ProgressBar Control auf Ihre XAML Seite ziehen. Dadurch wird der XAML Seite der folgende Code hinzugefügt.
<ProgressBar Name="progressBar1" Value="0"></ProgressBar>
Die Eigenschaften des Controls können Sie je nach Bedarf anpassen.
Um die ProgressBar im Determinate Mode zu verwenden, müssen Sie sicher gehen, dass die Checkbox IsIndeterminate nicht gecheckt ist. Mit den Werten Minimum und Maximum bestimmen Sie den Wertebereich der Fortschrittsanzeige und mit Value den aktuellen Wert.
Während Ihre Operation Fortschritt macht, setzen Sie im code-behind den Wert von Value auf einen entsprechenden Wert zwischen Minimum und Maximum. Wenn Sie Value auf einen Wert außerhab der Grenzen von Minimum und Maximum setzen, wird die Progressbar einfach 0 oder 100 Prozent anzeigen.
ProgressIndicator
Der zweite Weg zur Fortschrittsanzeige ist über den ProgressIndicator. Dieses Control wird in der System Tray angezeigt, so wie unten zu erkennen. Das erste Bild zeigt die System Tray im „Normalzustand“. Das zweite Bild zeigt die eingeblendete ProgressBar.
Um den ProgressIndicator zu verwenden, fügen Sie das folgende using Statement in der code-behind Datei hinzu.
using Microsoft.Phone.Shell;
Den eigentlichen ProgressIndicator anlegen und der System Tray hinzufügen können Sie dann etwa so:
ProgressIndicator progressIndicator = new ProgressIndicator() { IsVisible = true, IsIndeterminate = false, Text = "Downloading file ..." }; SystemTray.SetProgressIndicator(this, progressIndicator);
Achten Sie darauf, dass die Eigenschaft Value des ProgressIndicator immer zwischen 0 und 1 sein muss. Hier haben Sie nicht die Möglichkeit, eigene Grenzen mit Minimum und Maximum anzugeben.
Beispielanwendung
In unserer Beispielanwendung „Day15-ProgressBar“ wollen wir beide Controls ausprobieren:
Im XAML unten haben wir alle notwendigen Controls definiert: Es gibt eine ProgressBar, zwei Buttons, um einen Timer zu starten und anzuhalten (dieser wird unsere Operation simulieren), und einen Slider, mit welchem wir den Wert des ProgressIndicator verändern können.
<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 Benutzeroberfläche lassen Sie uns den C# code-behind anschauen.
Zunächst fügen wir einige using Statements ein für die Controls, die wir verwenden werden. Für den ProgressIndicator nutzen wir den Namespace Microsoft.Phone.Shell. Innerhalb der Klasse definieren wir einige Variablen. Wir erstellen einen ProgressIndicator, den wir später in die SystemTray hängen werden. Ein DispatcherTimer erstellen wir, um eine länger dauernde Operation zu simulieren. Im Konstruktur hängen wir das Objekt progressIndicator in die SystemTray und initialisieren den Timer, so dass er die Methode timer_Tick alle 5000 Ticks aufruft.
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 feuert und damit die Methode timer_Tick aufgerufen wird, erhöhen wir den Wert der Eigenschaft Value der progressBar. Dadurch macht es den Anschein, als mache unsere simulierte Operation Fortschritt.
Fehlen noch die Methoden für die Button Click Events. Diese starten und stoppen den Timer — sie starten und beenden also unsere lang dauernde Operation. Wenn man den Start Button drückt, wird der Wert der Eigenschaft Value der progressBar auf 0 zurückgesetzt und der Timer gestartet. Der Stop Button setzt ebenfalls den Wert auf 0 und hält den Timer an.
Die letzte verbliebene Methode ist der Event Handler slider1_ValueChanged, die aufgerufen wird, wenn der Anwender den Slider bewegt. Die Position des Sliders werden wir verwenden, um den Wert des ProgressIndicator zu setzen.
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 diesem Artikel haben Sie gesehen, wie man die veschiedenen Fortschrittsanzeigen in einer Windows Phone Mango Anwendung verwenden kann. Mit wenigen Zeilen Code können Sie komplette Fortschrittsanzeigen zu einer Silverlight Windows Phone Anwendung hinzufügen. Sie können entweder einen ProgressIndicator erstellen, der in der SystemTray angezeigt wird, oder eine ProgressBar, die irgendwo auf der Seite angezeigt werden kann.
Fortschrittsanzeigen sind ein wesentlicher Bestandteil von Anwendungen, die längere Operationen durchführen. Sie geben dem Anwender das Gefühl, dass die Anwendung noch am Leben ist und arbeitet. Die Anwender fühlen sich wohler, wenn Sie über den Fortschritt der Anwendung Bescheid wissen.
Um eine lauffähige Version der Anwendung dieses Artikels herunterzuladen, drücken Sie auf den Download Code Button.
Morgen werden wir uns den Isolated Storage Explorer anschauen. Damit können Sie von Ihrer Anwendung im Emulator oder auf einem echten Gerät gespeicherte Daten ansehen und untersuchen. Samidip Basu wird Ihnen alles rund um dieses neue Feature erklären.
Bis dahin!