IT tutorials
 
Mobile
 

Windows Phone 8 : Range Controls (part 2) - Progress Indicator, Slider , ScrollBar

1/18/2015 8:20:17 PM
- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire

Progress Indicator

In the initial release of the Windows Phone OS, there was no way to control the native progress bar located in the status bar of the phone. Fortunately, since the release of Windows Phone 7.5, you can with the ProgressIndicator class.

ProgressIndicator is a subclass of the DependencyObject class and provides the following bindable properties:

- IsIndeterminateA bool value that allows you to enable or disable the indeterminate state of the indicator.

- IsVisibleA bool value that allows you to show or hide the ProgressIndicator.

- TextA string that is displayed beneath the indicator.

- ValueA double value between 0.0 and 1.0 that allows you to set the length of the progress bar when in determinate mode, that is, when IsIndeterminate is set to false.


Note

The default value of ProgressIndicator.IsVisible is false. You must set IsVisible to true, either explicitly or via a data binding for the control to be displayed.


A ProgressIndicator may be either defined in XAML or in code. The following example demonstrates adding a ProgressIndicator to a page’s XAML file:

<phone:PhoneApplicationPage
...
    shell:SystemTray.IsVisible="True">

    <shell:SystemTray.ProgressIndicator>
        <shell:ProgressIndicator IsVisible="True"
                                 IsIndeterminate="False"
                                 Value="0.9"
                                 Text="{Binding Message}" />
    </shell:SystemTray.ProgressIndicator>
...
</phone:PhoneApplicationPage>


Note

SystemTray.IsVisible must be set to true for the ProgressIndicator to be displayed.


Adding a ProgressIndicator to a page must occur after the page has been initialized. This can be done by attaching the ProgressIndicator to the page within a Loaded event handler.

The ProgressIndicator instance may be retained as a field in the page and used directly, or data bindings can be established when the ProgressIndicator is instantiated, as demonstrated in Listing 1.

LISTING 1. Initializing a ProgressIndicator in Code


public partial class ExampleView : PhoneApplicationPage
{
    public ExampleView()
    {
        InitializeComponent();
        DataContext = new ExampleViewModel();
        Loaded += HandleLoaded;
    }

    void HandleLoaded(object sender, RoutedEventArgs e)
    {
        var progressIndicator = SystemTray.ProgressIndicator;
        if (progressIndicator != null)
        {
            return;
        }

        progressIndicator = new ProgressIndicator();

        SystemTray.SetProgressIndicator(this, progressIndicator);

        Binding binding = new Binding("Busy") { Source = ViewModel };
        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.IsVisibleProperty, binding);

        binding = new Binding("Busy") { Source = ViewModel };
        BindingOperations.SetBinding(
            progressIndicator,
            ProgressIndicator.IsIndeterminateProperty,
            binding);

        binding = new Binding("Message") { Source = ViewModel };
        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.TextProperty, binding);
    }
...
}



Best Practice

Performing time-consuming operations, such as downloads and database queries, on the UI thread is bad practice, as it locks the user interface making it unresponsive. Therefore, always perform any potentially long-running operation using a background thread.


Using a BackgroundWorker to Update the ProgressBar

The BackgroundWorker class allows you to run an operation on a separate, dedicated thread. When you want a responsive user interface and you must perform time-consuming operations, the BackgroundWorker class provides a convenient solution.

The BackgroundWorker class has events that are automatically raised on the UI thread, giving you the opportunity to update UIElements without risking cross-thread access exceptions. You can listen for events that report the progress of an operation and signal when the operation is completed. The following section uses a BackgroundWorker to perform an arbitrary time-consuming operation during which a ProgressBar is periodically notified of the progress.

ProgressBar and BackgroundWorker Sample Code

An example for the ProgressBar can be found in the ControlExamplesView page and the ControlExamplesViewModel class in the downloadable sample code.

The viewmodel contains a BackgroundWorker field. In the viewmodel’s constructor, the BackgroundWorker.WorkerReportsProgress property is set to true. This causes the BackgroundWorker to raise an event when its ReportProgress method is called. We then subscribe to three events: the DoWork event, which is raised when the RunWorkerAsync method is called; the ProgressChanged event, which is called when the BackgroundWorker ReportProgress method is called; and the RunWorkerCompleted, which is raised when the backgroundWorker_DoWork method completes (see Listing 2).

LISTING 2. ControlExamplesViewModel Class (excerpt)


public class ControlExamplesViewModel : ViewModelBase
{
    readonly BackgroundWorker backgroundWorker = new BackgroundWorker();

    public ControlExamplesViewModel()
        : base("Controls")
    {
        backgroundWorker.WorkerReportsProgress = true;
        backgroundWorker.DoWork
            += new DoWorkEventHandler(backgroundWorker_DoWork);
        backgroundWorker.ProgressChanged
            += new ProgressChangedEventHandler(
                        backgroundWorker_ProgressChanged);
        backgroundWorker.RunWorkerCompleted
            += new RunWorkerCompletedEventHandler(
                backgroundWorker_RunWorkerCompleted);

        backgroundWorker.WorkerSupportsCancellation = true;
        cancelProgressCommand = new DelegateCommand(
            obj => backgroundWorker.CancelAsync());

        backgroundWorker.RunWorkerAsync();
        Message = "BackgroundWorker performing task.";
    }
    void backgroundWorker_ProgressChanged(
            object sender, ProgressChangedEventArgs e)
    {
        ProgressPercent = e.ProgressPercentage;
    }

    void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = (BackgroundWorker)sender;
        for (int i = 0; i < 100; i++)
        {
            if (worker.CancellationPending)
            {
                e.Cancel = true;
                return;
            }
            Wait(300);
            worker.ReportProgress(i);
        }
    }
    void backgroundWorker_RunWorkerCompleted(
            object sender, RunWorkerCompletedEventArgs e)
    {
        Message = e.Cancelled
            ? "Background worker cancelled."
            : "Background worker completed.";
    }

    int progressPercent;

    public int ProgressPercent
    {
        get
        {
            return progressPercent;
        }
        private set
        {
            Assign(ref progressPercent, value);
        }
    }
    bool cancelProgress;
    DelegateCommand cancelProgressCommand;

    public ICommand CancelProgressCommand
    {
        get
        {
            return cancelProgressCommand;
        }
    }

    string message;

    public string Message
    {
        get
        {
            return message;
        }
        set
        {
            Assign(ref message, value);
        }
    }

    static readonly object waitLock = new object();

    static void Wait(int delayMs)
    {
        if (delayMs > 0)
        {
            lock (waitLock)
            {
                Monitor.Wait(waitLock, delayMs);
            }
        }
    }
}


While running, the worker thread repeatedly sleeps, using the viewmodel’s Wait method, and then signals that the progress has changed.


Note

If the BackgroundWorker.WorkerReportsUpdates property is set to false and the BackgroundWorker ReportProgress method is called, an InvalidOperationException will be thrown.


The following excerpt shows the view’s XAML for the relevant controls:

<TextBlock Text="ProgressBar" />
<ProgressBar Value="{Binding ProgressPercent}"
        Minimum="0" Maximum="100" />
<Button Content="Cancel Progress"
        Command="{Binding CancelProgressCommand}" />
<TextBlock Text="Message" />
<TextBlock Text="{Binding Message}" Height="80" />

On completion of the backgroundWorker_DoWork method, the backgroundWorker_RunWorkerCompleted method is called, and the viewmodel’s MessageProperty is updated (see Figure 3).

Image

FIGURE 3 Updating the UI using a BackgroundWorker.

The BackgroundWorker class also supports operation cancellation. By pressing the Cancel Progress button, the CancelProgressCommand is executed, which, in turn, calls the backgroundWorker’s CancelAsync method. This is then detected in the backgroundWorker_DoWork method, which sets the Cancel property of the DoWorkEventArgs.

Although cancelled, the BackgroundWorker.RunWorkCompleted event is still raised, and the backgroundWorker_RunWorkerCompleted handler is still called; however, the RunWorkerCompletedEventArgs.Cancelled property allows you to determine whether the operation was cancelled.


Note

The NotifyPropertyChangeBase class in the downloadable sample code, which is the base class of the ViewModelBase class, automatically raises INotifyPropertyChanged.PropertyChanged events on the UI thread (one of its many benefits). Therefore, you could achieve the same thing shown in the example by replacing the BackgroundWorker with a thread from, for example, the ThreadPool, and by including two Boolean cancel and cancelled fields. It would make for a simpler implementation with fewer event subscriptions.

Slider

The Slider is an interactive control that allows the user to set its Value property by dragging or pressing the Slider track. It is ideal for values that do not require a high level of precision, such as the volume setting for music in a game.

The following demonstrates how to define a Slider in XAML:

<Slider Value="5" Minimum="0" Maximum="100" LargeChange="20" />

The Value, Minimum, and Maximum properties are described in the previous section on the RangeBase control.

When the user taps the Slider track, the Value property is incremented or decremented by the value of the LargeChange property.

The default orientation of the Slider is horizontal. The orientation can be changed by setting the Orientation property to Vertical.

The Slider is an especially useful control on the Windows Phone platform, since the use of touch makes the slider easier to control than it would otherwise be with the mouse.


Note

The built-in Slider control is, however, somewhat cumbersome to use. The control template for the Slider was built for Silverlight for the Browser, where mice are better at hitting small targets. A number of custom templates are available on the Web that provide better usability. Dave Relyea, the lead developer of the Windows Phone Toolkit team, provides an improved Slider control. See http://bit.ly/b0YtQj for more information.

Best Practice

Do not place a horizontal Slider control on a Pivot or Panorama control. Doing so may interfere with a user’s ability to move between items, or it may prevent a user from manipulating the Slider without moving between Panorama or Pivot items. This also applies to other controls like the Bing Maps control, which rely on the user performing a drag gesture.

Note that you may see a Slider placed in a Pivot in the sample code. This has been done for the sake of convenience and should not be taken as guidance.

ScrollBar

ScrollBar is a control that has a sliding thumb whose position corresponds to a value. The ScrollBar class provides a ViewportSize property, which determines the amount of scrollable content that is visible and an Orientation property, which can be either Horizontal or Vertical.

It is rare to see the ScrollBar used directly. It is more commonly used within other controls such as the ScrollViewer or in custom controls.

 
Others
 
- Windows Phone 8 : Range Controls (part 1) - ProgressBar
- Windows Phone 8 : Items Controls - ListBox, ComboBox
- Windows Phone 8 : LinkedIn (part 3) - Posting a Message, The Feeds Filter
- Windows Phone 8 : LinkedIn (part 2) - Accessing LinkedIn Content, Responding to a LinkedIn Post
- Windows Phone 8 : LinkedIn (part 1) - Configuring Your LinkedIn Account
- Windows Phone 8 : Twitter (part 2) - Checking for Tweets, Responding to a Tweet, Checking Twitter Notifications
- Windows Phone 8 : Twitter (part 1) - Configuring Your Twitter Account
- Windows Phone 8 : Working with People - The Me Tile (part 4) - Chatting with Friends, Setting Your Chat Status, Notifications
- Windows Phone 8 : Working with People - The Me Tile (part 3) - Uploading a Photo
- Windows Phone 8 : Working with People - The Me Tile (part 2) - Posting Status Updates, Checking In
 
25 Inspiring Game of Thrones Quotes
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
programming4us programming4us
 
Popular tags
 
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS