Search code examples
c#wpfprogress-bar.net-6.0

Update progress bar value while processing in WPF


I have a screen which used to check connection with multiple devices by COM/USB Port as the below picture https://i.sstatic.net/CAjK0.png

When user click button Check Device if checking a device connection is finished, icon good or not good will display next to combobox and progress bar will update value based on total of devices. For example, there are 4 devices then progress bar will update 25%, 50%, 75%, 100% after checking.

I tried to use PropertyChanged to update value but it's seem not working. After clicking button, the progress bar is visible but value is always 100. Please help me with this!

Here is my code:

File xaml:

<ProgressBar x:Name="pgProcessing" Visibility="Collapsed" Minimum="0" Maximum="100" Value ="{Binding Percent, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>

Code behind:

    private double _percent;
    public double Percent
        {
            get { return _percent; }
            set { _percent = value; OnPropertyChanged("Percent"); }
        }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }

    private void BtnCheck_Click(object sender, RoutedEventArgs e)
        {
            pgProcessing.Visibility = Visibility.Visible;
            _percent = 0;
            this.Percent = _percent;               
   
            // Do check connection 1st device
            // End

            _percent = (100 * currentDevice) / TOTAL_DEVICE;
            this.Percent = _percent; //50%

            // Do check connection 2nd device
            // End

            _percent = (100 * currentDevice) / TOTAL_DEVICE;
            this.Percent = _percent; //100%
        }       

My constructor:

    public HealthCheck()
        {
            InitializeComponent();
            this.DataContext = this;
        }

I also implement INotifyPropertyChanged in the cs file


Solution

  • Seems you are confusing how the Binding works. My recommendation would be to use MVVM pattern and not mix stuff up (if possible). To solve you problem there are two ways. First let the code behind remain code behind. All you need is to assign the Value directly to the progress bar like this:

       private async void Button_Click(object sender, RoutedEventArgs e)
        {
            pgProcessing.Visibility = Visibility.Visible;
            pgProcessing.Value = 0;
    
            await Task.Delay(100);
            pgProcessing.Value = 25;
            await Task.Delay(100);
            pgProcessing.Value = 50;
            await Task.Delay(100);
            pgProcessing.Value = 75;
            await Task.Delay(100);
            pgProcessing.Value = 100;
        } 
    

    However if you would like to use MVVM, I you can call the property changes on the model via code behind as well. Example :

    public class Model : INotifyPropertyChanged
    {
        private double _percent;
        public double Percent
        {
            get { return _percent; }
            set { _percent = value; OnPropertyChanged("Percent"); }
        }
    
        public event PropertyChangedEventHandler? PropertyChanged;
        private void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
    

    and your *xaml.cs :

     public partial class MainWindow : Window
        {
            readonly Model _model;
            public MainWindow()
            {
                InitializeComponent();
                _model = new Model();
                DataContext = _model;
            }
    
            private async void Button_Click(object sender, RoutedEventArgs e)
            {
                pgProcessing.Visibility = Visibility.Visible;
                _model.Percent = 0;
    
                await Task.Delay(100);
                _model.Percent = 25;
                await Task.Delay(100);
                _model.Percent = 50;
                await Task.Delay(100);
                _model.Percent = 75;
                await Task.Delay(100);
                _model.Percent = 100;
            }
        }
    

    Regardless, I suggest to implement Icommand/relayCommand pattern into your ViewModel as well and proccess button press also within View Model.