TOC

This article has been localized into Danish by the community.

Diverse kontroller:

ProgressBar kontrollen

WPF kommer med en nydelig kontrol til visning af status ved navn ProgressBar. Den virker ved at sætte en minimum og maksimum værdi og derefter øge en værdi, hvilket giver en visuel indikation om hvor langt i processen, du er for øjeblikket. Her er et meget elementært eksempel til at demonstrere det med:

<Window x:Class="WpfTutorialSamples.Misc_controls.ProgressBarSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ProgressBarSample" Height="100" Width="300">
    <Grid Margin="20">
        <ProgressBar Minimum="0" Maximum="100" Value="75" />
    </Grid>
</Window>

I dette tilfælde har jeg brugt en ret generel tilgang til at vise status som en procent (mellem 0 og 100%) med en startværdi på 75. En anden tilgang er at bruge aktuelle minimum og maksimumværdier fra en liste af opgaver, du udfører. F.eks. hvis du gennemløber en liste af filer, mens du thekker hver af dem, kan du sætte Minimum egenskaben til 0, Maximum til antallet af filer i listen, og derefter bare tælle op som du løber gennem dem.

ProgressBar er ganske som andre standard WPF kontroller gengivet til at matche den visuelle typografi på operativsystemet. Her på Windows 7 har den en fin animeret graduering, som vist på skærmbilledet.

Vise status ved udførelse af en langvarig opgave

Ovenstående eksempel illustrerer hvor simpelt, det er at bruge en ProgressBar kontrol, men normalt vil du selvfølgelig ønske at vise status på en aktuel opgave og ikke bare en statisk værdi.

I de fleste tilfælde til du bruge ProgressBar til at vise status for en tung/langvarig opgave, og dette er hvor de fleste nye programmører render ind i ret almindelige problemer: Hvis du laver en tung opgave på UI tråden, mens du forsøger at opdatere f.eks. en PogressBar kontrol, vil du hurtigt finde ud af, at du ikke kan begge dele på samme tid på den samme tråd. Eller for at være mere klar, du kan, men PogrressBar vil faktisk ikke vise hver opdatering af status før opgaven er fuldført, hvilket er ret så ubrugeligt.

For at illustrere det, kan du prøve det følgende eksempel:

<Window x:Class="WpfTutorialSamples.Misc_controls.ProgressBarTaskOnUiThread"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ProgressBarTaskOnUiThread" Height="100" Width="300"
        ContentRendered="Window_ContentRendered">
    <Grid Margin="20">
        <ProgressBar Minimum="0" Maximum="100" Name="pbStatus" />
    </Grid>
</Window>
using System;
using System.Threading;
using System.Windows;

namespace WpfTutorialSamples.Misc_controls
{
	public partial class ProgressBarTaskOnUiThread : Window
	{
		public ProgressBarTaskOnUiThread()
		{
			InitializeComponent();
		}

		private void Window_ContentRendered(object sender, EventArgs e)
		{
			for(int i = 0; i < 100; i++)
			{
				pbStatus.Value++;
				Thread.Sleep(100);
			}
		}
	}
}

Et meget elementært eksempel, hvor vi, så snart vinduet er klar, foretager en løkke fra 0 til 100, og i hvert gennemløb øger værdien på ProgressBar. Enhver moderne computer kan gøre dette hurtigere end du kan blinke med øjnene, så jeg har tilføjet en forsinkelse i hvert gennemløb på 100 millisekunder. Desværre, som jeg allerede har beskrevet, sker der ingenting. Dette er hvordan, det ser ud i midten af processen:

Bemærk, at markøren indikerer, at der sker noget, men ProgressBar ser stadig ud, som den gjorde ved start (tom). Så snart løkken, der repræsenterer din langvarige opgave, er færdig, ser ProgressBar således ud:

Det hjalp ikke rigtig dine brugere til at se status! I stedet er vi nødt til at udføre arbejdet på en arbejstråd og derefter skubbe opdateringerne til UI tråden, som så vil være i stand til at behandle og visuelt vise disse opdateringer med det samme. Et glimrende værktøj til at håndtere dette job er BackgroundWorker klassen, som vi vil snakke meget mere om et andet sted i dette selvstudie. Her er det samme eksempel som ovenfor, men denne gang med anvendelse af en BackgroundWorker:

<Window x:Class="WpfTutorialSamples.Misc_controls.ProgressBarTaskOnWorkerThread"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ProgressBarTaskOnWorkerThread" Height="100" Width="300"
        ContentRendered="Window_ContentRendered">
    <Grid Margin="20">
        <ProgressBar Minimum="0" Maximum="100" Name="pbStatus" />
    </Grid>
</Window>
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;

namespace WpfTutorialSamples.Misc_controls
{
	public partial class ProgressBarTaskOnWorkerThread : Window
	{
		public ProgressBarTaskOnWorkerThread()
		{
			InitializeComponent();
		}

		private void Window_ContentRendered(object sender, EventArgs e)
		{
			BackgroundWorker worker = new BackgroundWorker();
			worker.WorkerReportsProgress = true;
			worker.DoWork += worker_DoWork;
			worker.ProgressChanged += worker_ProgressChanged;

			worker.RunWorkerAsync();
		}

		void worker_DoWork(object sender, DoWorkEventArgs e)
		{
			for(int i = 0; i < 100; i++)
			{
				(sender as BackgroundWorker).ReportProgress(i);
				Thread.Sleep(100);
			}
		}

		void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			pbStatus.Value = e.ProgressPercentage;
		}
	}
}

Som du kan se på skærmbilledet, bliver status nu opdateret hele vejen gennem opgaven, og som markøren indikerer, sker der ikke noget tungt arbejde på UI tråden, hvilket betyder, at du stadig kan interagere med resten af interfacet.

Vær opmærksom på, at mens BackgroundWorker hjælper en del med problemer relateret til multitrådning, er der stadig nogle ting, du skal være opmærksom på, så kig endelig på BackgroundWorker artiklerne i dette selvstudie før du laver nogle mere avancerede scenarier end eksemplet ovenfor.

Ubestemt

For nogle opgaver kan oplysning om status som en procent ikke være muligt, eller du ved simpelthen ikke hvor lang tid, det vil vare. Til disse situationer er den ubestemte statuslinje blevet opfundet, hvor en animation lader brugeren vide, at der sker noget, og samtidig indikerer, at kørselstiden ikke kan afgøres.

WPF ProgressBar understøtter denne tilstand gennem brug af IsIndeterminate egenskaben, som vi viser dig i næste eksempel.

<Window x:Class="WpfTutorialSamples.Misc_controls.ProgressBarIndeterminateSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ProgressBarIndeterminateSample" Height="100" Width="300">
    <Grid Margin="20">
        <ProgressBar Minimum="0" Maximum="100" Name="pbStatus" IsIndeterminate="True" />
    </Grid>
</Window>

Bemærk, at den grønne statusindikator ikke er forankret til nogle af siderne - i stedet flyder den frit fra start til slut og starter derefter forfra.

ProgressBar med tekst

En ting, jeg virkelig savnede fra standard WPF ProgressBar er evnen til at vise en tekstrepræsentation af status såvel som statuslinjen. Heldigvis for os gør fleksibiliteten i WPF det meget nemt for os at opnå. Her er et eksempel:

<Window x:Class="WpfTutorialSamples.Misc_controls.ProgressBarTextSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ProgressBarTextSample" Height="100" Width="300">
    <Grid Margin="20">
        <ProgressBar Minimum="0" Maximum="100" Value="75" Name="pbStatus" />
        <TextBlock Text="{Binding ElementName=pbStatus, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</Window>

Vi opnår ovenstående ved at placere ProgressBar og TextBlock til visning af procentdelen i det samme Grid uden at angive nogen rækker eller kolonner. Dette vil gengive TextBlock oven på ProgressBar, hvislket er nøjagtig hvad, vi ønsker, da TextBlock har en gennemsigtig baggrund som standard.

Vi bruger en binding for at være sikker på, at TextBlock viser den samme værdi som ProgressBar. Bemærk den specielle StringFormat syntaks, der tillader os at vise værdien med et procenttegn tilføjet - det ser måske lidt underligt ud, men se StringFormat artiklen i dette selvstudio for mere information om det.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!