#1,030 – Displaying an Indeterminate Progress Bar

When you display a ProgressBar to show progress on some background task, you often know how much work needs to be done and how much of the work has already been done.  The ProgressBar below shows that we’ve loaded 5 out of 12 records, so the ProgressBar is 42% full.

1074-001

In other cases, you may want to use a ProgressBar to show the user that something is happening, but you might not know how long the operation will take or how much of the total work has already been done.  In these cases, you can display an “indeterminate” progress bar by setting the IsIndeterminate property to true.  A green bar will repeatedly slide across the face of the ProgressBar to show that something is happening.

        <ProgressBar IsIndeterminate="True"
                     Height="15" Margin="15,15,15,0"/>
        <Label Content="Connecting to database..."
               Margin="10,0"/>

1030-001
When the operation is done, you can just set IsIndeterminate to false and set Value to 0.

#1,029 – Simple ProgressBar Example

Here’s an example of how we could use a ProgressBar in an application to show # records processed.

    <StackPanel>
        <ProgressBar Value="{Binding NumRecsLoaded}" Maximum="{Binding TotalNumRecs}"
                     Height="15" Margin="15,15,15,0"/>
        <Label Content="{Binding RecsLoadedMessage}"
               Margin="10,0"/>
        <Button Margin="15" Padding="15,3" HorizontalAlignment="Center"
            Content="Start" Click="Button_Click"/>
    </StackPanel>

In code, we declare properties for total number of records and number already loaded. When the user clicks on the Button, we set up a timer that increments the # records loaded each time that it ticks (twice a second).  (Note–to use the DispatcherTimer, you need to use namespace System.Windows.Threading).

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private int numRecsLoaded = 0;
        public int NumRecsLoaded
        {
            get { return numRecsLoaded; }
            protected set
            {
                numRecsLoaded = value;
                RaisePropertyChanged("NumRecsLoaded");
                RaisePropertyChanged("RecsLoadedMessage");
            }
        }

        private int totalNumRecs = 12;
        public int TotalNumRecs
        {
            get { return totalNumRecs; }
            protected set
            {
                totalNumRecs = value;
                RaisePropertyChanged("TotalNumRecs");
            }
        }

        public string RecsLoadedMessage
        {
            get { return string.Format("Loaded {0} records...", numRecsLoaded);  }
        }

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

        }

        // INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        private void RaisePropertyChanged(string propName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DispatcherTimer timer = new DispatcherTimer();
            timer.Tick += (s,ea) =>
            {
                NumRecsLoaded++;
                if (NumRecsLoaded == TotalNumRecs)
                    timer.Stop();
            };
            timer.Interval = new TimeSpan(0, 0, 0, 0, 500);  // 2/sec
            timer.Start();
        }
    }

1074-001

#1,028 – ProgressBar Basics

You’ll often want to let a user know that something is happening in the background in your application.  For example, you might be processing some records or calculating a result.

You could use a simple busy indicator to show that something is happening.  But you may also want to show how much of the operation is complete, giving the user a sense of how much work remains and how fast the work is being done.

To show progress in this way, you can use a ProgressBar control.  The ProgressBar has a range, represented by its Minimum and Maximum values and a current Value falling within that range.  You typically update the Value periodically, so that it increases from Minimum to Maximum as the work progresses.

In the example below, we’ve set the Value to 75, where Minimum and Maximum are 0 and 100, respectively.  The Value is represented by the shaded green bar.

1073-001

#1,027 – Displaying a Subrange on a Slider

You can highlight a sub-range on a Slider that is some subset of the full range.  You do this by setting the IsSelectionRangeEnabled property to true and setting SelectionStart and SelectionEnd to the desired start and end values for the range.  The sub-range is displayed using a different color.  Triangular indicators are displayed on the tickmark bar to show the start and end of the range.

Displaying a sub-range in this manner has no effect on the values that you’re allowed to pick with the Slider.  It’s merely a visual indicator.

        <Label Content="Set your Age.  (Subrange is typical working age)."/>
        <Slider Name="mySlider" Margin="10" Foreground="Blue"
                Minimum="0" Maximum="100"
                IsSelectionRangeEnabled="True"
                SelectionStart="22" SelectionEnd="65"
                TickPlacement="BottomRight"
                TickFrequency="5" />
        <StackPanel Orientation="Horizontal">
            <Label Content="Value:" />
            <TextBlock Text="{Binding Value, ElementName=mySlider, StringFormat={}{0:0}}"
                       VerticalAlignment="Center"/>
        </StackPanel>

1027-001

#1,026 – Horizontal and Vertical Sliders

You can orient a Slider either horizontally or vertically by setting the Orientation property to Horizontal (the default) or Vertical.  The thumb on the Slider will be rendered differently, depending on the orientation.

Below is an example of both a horizontal and a vertical Slider.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Label Content="Width" VerticalAlignment="Center"/>
            <Slider Grid.Column="1" Margin="10" Foreground="Blue"
                    Minimum="1" Maximum="5"
                    TickPlacement="BottomRight"/>
        </Grid>

        <Slider Grid.Row="1" Margin="10,0" Foreground="Blue"
                Minimum="1" Maximum="10"
                Orientation="Vertical"
                TickPlacement="BottomRight"/>
        <Label Grid.Row="2" Content="Height"/>
    </Grid>

1026-001

#1,025 – Small and Large Changes to the Value of a Slider

When you use the mouse to drag the thumb of a Slider control, you can set the value of the slider to any value within its range.  (This is true unless you’ve set the IsSnapToTickEnabled property to true, in which case you’re constrained to values at tickmarks).

You can also increase or decrease the value of the Slider by:

  • Using the arrow keys on the keyboard – changes value by SmallChange property amount – default 0.1
  • Left-clicking in the Slider on one side of the thumb or the other – changes value by LargeChange property amount – default 1.0

You can change these default values by setting the SmallChange and/or LargeChange properties.

For example:

<Slider Name="mySlider" Margin="10"
        Minimum="0" Maximum="50"
        SmallChange="1" LargeChange="5"/>

With these changes, you can now use the arrow keys to change the Slider’s value by 1.0 and can left-click next to the thumb to change the value by 5.0.

#1,024 – Making a Slider Cycle through Values of an Enumerated Type

You may want to use a Slider control to let a user select from a set of values specified by an enumerated type.  For example, you could let users select a day of the week from the DayOfWeek enumerated type.

Here’s one way to do that.  In XAML, define Slider and TextBlock that uses a value converter to display the day.

    <Window.Resources>
        <local:DayOfWeekEnumToStringValueConverter x:Key="dayOfWeekEnumToStringConverter"/>
    </Window.Resources>

    <StackPanel>
        <Slider Name="mySlider" Margin="10"
                Minimum="0"
                IsSnapToTickEnabled="True"/>

        <TextBlock Text="{Binding Path=Value, ElementName=mySlider, Converter={StaticResource dayOfWeekEnumToStringConverter}}"
                    Margin="10"/>
    </StackPanel>

The value converter code could be:

    public class DayOfWeekEnumToStringValueConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            DayOfWeek day = (DayOfWeek)((double)value);
            return day.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

All that remains is to set the Maximum property. This can be done in code-behind (e.g. in the main window’s constructor):

            mySlider.Maximum = Enum.GetNames(typeof(DayOfWeek)).Length - 1;

1024-001

#1,023 – Displaying a Tooltip that Shows the Value of a Slider

You can use the AutoToolTipPlacement property to automatically show a tooltip on a slider while the thumb is being dragged.  The tooltip will show the current Value of the slider.

You can set AutoToolTipPlacement to either BottomRight or TopLeft to control the position of the tooltip.  (The default is None).

Note, however, that the value shown in the tooltip is by default rounded to the nearest integer.  You can see this in the example below, as we display the actual Value in a TextBlock.

        <Slider Name="mySlider" Margin="10"
                Minimum="1" Maximum="100"
                AutoToolTipPlacement="BottomRight"/>

1023-001
You can increase the precision shown in the tooltip by setting the AutoToolTipPrecision property.  You set this property to be the number of digits to the right of the decimal place that you want to see.

        <Slider Name="mySlider" Margin="10"
                Minimum="1" Maximum="100"
                AutoToolTipPlacement="BottomRight"
                AutoToolTipPrecision="2"/>

1023-002

#1,022 – Render Tick Marks in a Different Color

By default, tick marks on a Slider are rendered in a light grey color that is a bit tough to see.

1022-001

You can change the color used to display the tick marks by setting the Foreground property of the Slider.

        <Slider Name="mySlider" Margin="10"
                Minimum="1" Maximum="10"
                IsSnapToTickEnabled="True"
                TickPlacement="BottomRight"
                TickFrequency="2"
                Foreground="Blue"/>

1022-002

#1,021 – Two Ways to Position Tick Marks on a Slider

You can cause tick marks to be displayed with a Slider control by setting the TickPlacement property.  By default, this places tick marks every 1 unit between the Minimum and Maximum values (inclusive).

There are two ways to change where tick marks are displayed on the Slider.  The first is to set the TickFrequency to indicate the desired spacing between tick marks.  When you set TickFrequency:

  • Tick mark is displayed at Minimum value
  • Tick marks are displayed at Minimum + TickFrequency and then every TickFrequency units
  • Tick mark is displayed at Maximum value

For example, if Minimum is 1, Maximum is 10, and TickFrequency is 2, we get tick marks at: 1, 3, 5, 7, 9, 10.

1021-001

The second method for configuring tick marks is to list a series of positions using the Ticks property.  Ticks are placed at the specified locations, as well as the Minimum and Maximum location.

        <Slider Minimum="1" Maximum="10"
                IsSnapToTickEnabled="True"
                TickPlacement="BottomRight"
                Ticks="2,4,6,8"/>

1021-002

Follow

Get every new post delivered to your Inbox.

Join 311 other followers