在WPF中在处理过程中更新进度条的数值。

huangapple go评论65阅读模式
英文:

Update progress bar value while processing in WPF

问题

我有一个屏幕,用于通过COM/USB端口检查与多个设备的连接,如下图所示:
链接到图片

当用户点击“检查设备”按钮时,如果检查设备连接完成,好或不好的图标将显示在组合框旁边,并且进度条将根据设备总数更新值。例如,如果有4个设备,那么进度条将在检查后更新为25%、50%、75%、100%。

我尝试使用PropertyChanged来更新值,但似乎不起作用。单击按钮后,进度条可见,但值始终为100。请帮我解决这个问题!

这是我的代码:

XAML 文件:

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

代码后台:

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;               

    // 检查第一个设备的连接
    // 结束

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

    // 检查第二个设备的连接
    // 结束

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

我的构造函数:

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

我也在 cs 文件中实现了 INotifyPropertyChanged。

英文:

I have a screen which used to check connection with multiple devices by COM/USB Port as the below picture
https://i.stack.imgur.com/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:

&lt;ProgressBar x:Name=&quot;pgProcessing&quot; Visibility=&quot;Collapsed&quot; Minimum=&quot;0&quot; Maximum=&quot;100&quot; Value =&quot;{Binding Percent, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}&quot;/&gt;

Code behind:

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

    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

答案1

得分: 2

代码部分不进行翻译,以下是翻译的内容:

"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 your 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:

然而,如果你想使用MVVM,你也可以在代码中调用模型上的属性更改。示例:

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 process button press also within ViewModel."

英文:

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(&quot;Percent&quot;); }
    }

    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.

huangapple
  • 本文由 发表于 2023年2月16日 14:51:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定