0

I have searched in Google using a progress bar in WPF that will be manually incremented and decremented using a plus and minus button. But, to no avail haven't found one that is similar to what I want though.

How do I implement a WPF progress bar that will be manually incremented or decremented (using buttons) in an MVVM way. The screen capture below shows the mock-up UI design.

enter image description here

The image show that when the user click the plus button, the progress bar will be incremented by 10 minutes. On the other hand, the minus button when clicked, decrements the progress bar by 10 minutes.

I'm just starting to learn WPF and MVVM. Any help is greatly appreciated.

Junius
  • 589
  • 2
  • 12
  • 41

2 Answers2

1

I created a simple example which uses WPF and MVVM to show how one model can be displayed with different views. Here in xaml I placed on a form Slider and ProgressBar - they are Views for our ViewModel. The properties we need (Minimum, Maximum, Value) are binded to the ViewModel's properties. "Plus" and "Minus" buttons' properties "Command" are also binded to the corresponding props in the ViewModel(IncreaseCommand, DecreaseCommand).

<Window>
    <StackPanel Orientation="Horizontal">
        <Button Width="50" Height="40" Content="-" Command="{Binding DecreaseCommand}"/>
        <StackPanel Width="400" Orientation="Vertical">
            <Slider Height="40" Margin="0,50,0,0" Minimum="{Binding Minimum}" Maximum="{Binding Maximum}" Value="{Binding Value}"/>
            <ProgressBar Height="40" Margin="0,100,0,0" Minimum="{Binding Minimum}" Maximum="{Binding Maximum}" Value="{Binding Value}"/>
            <TextBlock TextAlignment="Center" Margin="0,50,0,0" Text="{Binding Value}"/>
        </StackPanel>
        <Button  Width="50" Height="40" Content="+" Command="{Binding IncreaseCommand}"/>
    </StackPanel>
</Window>

For implementing the commands functionality in ViewModel you will need to create an implementation of ICommand interface:

public class RelayCommand : ICommand
{
    private Predicate<object> _canExecute;
    private Action<object> _execute;

    public RelayCommand(Predicate<object> canExecute, Action<object> execute)
    {
        _canExecute = canExecute;
        _execute = execute;
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

And here's the ViewModel class, it implements INotifyPropertyChanged interface to keep views updated.

public class ViewModel:INotifyPropertyChanged
{
    public ViewModel()
    {
        _value = 0;
        _minimum = 0;
        _maximum = 180;
        _step = 10;
    }

    private int _step;
    private int _minimum;
    private int _maximum;

    private ICommand _increaseCommand;
    public ICommand IncreaseCommand
    {
        get
        {
            if (_increaseCommand == null)
            {
                _increaseCommand = new RelayCommand(
                p => _value + _step <= _maximum,
                Increase);
            }
            return _increaseCommand;
        }
    }

    private ICommand _decreaseCommand;
    public ICommand DecreaseCommand
    {
        get
        {
            if (_decreaseCommand == null)
            {
                _decreaseCommand = new RelayCommand(
                p => _value - _step >= _minimum,
                Decrease);
            }
            return _decreaseCommand;
        }
    }


    private void Increase(object param)
    {
        Value = Value + _step;
    }

    private void Decrease(object param)
    {
        Value = Value - _step;
    }

    private int _value;
    public int Value
    {
        get { return _value; }
        set { _value = value; InvokePropertyChanged(new PropertyChangedEventArgs("Value")); }
    }

    public int Minimum
    {
        get { return _minimum; }
    }

    public int Maximum
    {
        get { return _maximum; }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void InvokePropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, e);
    }
}

And the last thing to get it all working is to create new ViewModel and set DataContext of a window to this model:

public MainWindow()
{
    InitializeComponent();
    var model = new ViewModel();
    DataContext = model;
}
lena
  • 1,181
  • 12
  • 36
  • this is awesome. I really appreciate your help. The piece of code you have written works well and the binding is really great. This is a good start for me on how to implement ICommand and INPC. You have saved my day. Thank you so much. – Junius Dec 23 '16 at 01:39
  • @Juniuz if you are a beginner in MVVM I may recommend you [Rachel's blog](https://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/), it helped me much in understanding the pattern and implementation of MVVM when I just started to learn it. – lena Dec 23 '16 at 06:02
  • yes I'm a newbie in MVVM. Thank you for sharing the blog. I'm sure it will help me much by writing more MVVM pattern based application. – Junius Dec 24 '16 at 02:02
  • I have another post, refer to this link http://stackoverflow.com/questions/40965739/how-to-show-floating-virtual-keyboard-user-control-in-mainwindow-when-an-input?noredirect=1#comment69146596_40965739, which is floating for a couple of weeks now. Maybe you could help me enlighten on how to solve the problem? Thanks in advance. – Junius Dec 24 '16 at 02:11
0

I think you should solve that by use custom Slider control of WPF instead Progress bar. This link can help you : http://www.codescratcher.com/wpf/custom-slider-control-in-wpf/

Rai Vu
  • 1,595
  • 1
  • 20
  • 30
  • thanks for sharing the link. The slider control makes sense compared to a progress bar. I have checked the custom slider control and, it does have the functionality that I need in UI perspective. However, it doesn't have an implementation on how to bind the slider control and buttons (+ and -) using MVVM? – Junius Dec 22 '16 at 03:23
  • @Juniuz have a property in Model and bind that to Slider's Value. If you update the Property, value will update (INotifyPropertyChanged must) – WPFUser Dec 22 '16 at 04:12