[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IProgress<int> to ProgressBar control #17521

Open
vpenades opened this issue Nov 15, 2024 · 7 comments
Open

Add IProgress<int> to ProgressBar control #17521

vpenades opened this issue Nov 15, 2024 · 7 comments

Comments

@vpenades
Copy link
vpenades commented Nov 15, 2024

Is your feature request related to a problem? Please describe.

ProgressBar control is used to display the progress of a task.

.Net has an interface, IProgress that is used as an abstracion of an UI object displaying the progress, so applications can report the progress of a task in a platform agnostic way.

So it would make sense that ProgressBar implements IProgress

Describe the solution you'd like

class ProgressBar : IProgress<ProgressChangedEventArgs>
{
    void IProgress<ProgressChangedEventArgs>.Report(ProgressChangedEventArgs progress)
    {
        // we may receive the progress report from another thread.
        Avalonia.Threading.Dispatcher.UIThread.Invoke(() => this.Value = progress.ProgressPercentage);
    }
}

Describe alternatives you've considered

Right now I'm using a wrapper:

class ProgressBarWithInterface : IProgress<int>
{
   private ProgressBar bar;

   void IProgress<int>.Report(int progress)
    {
        // we may receive the progress report from another thread.
        Avalonia.Threading.Dispatcher.UIThread.Invoke(() => bar.Value = progress);
    }
}

Additional context

.Net

Also has these types:

  • IProgress<T> interface
  • Progress<T> class
  • System.ComponentModel.ProgressChangedEventHandler
  • System.ComponentModel.ProgressChangedEventArgs

I think all these types are greatly underated, and ProgressBar could be made aware of them in some way.

No response

@robloo
Copy link
Contributor
robloo commented Nov 15, 2024

You are thinking about this in reverse I think. Any long running tasks or actions can report using IProgress.

However, the ProgressBar itself isn't a long running action. It is just a representation of progress and doesn't have any values of its own. It isn't doing any work, only displaying other work.

So ProgressBar can consume IProgress information. However, it doesn't report it itself, it needs to come from a lower layer.

If you application is pulling progress back out of a ProgressBar and using it elsewhere you have something designed wrong. There should be a common task in a lower layer that all code can consume progress information for. One of the consumers being the ProgressBar.

@vpenades
Copy link
Author

@robloo the IProgress is to be implemented in the controls displaying it, and consumed by the tasks.

the pseudocode would look like this:

View:

class ProgressBar : IProgress<int>
{
   // update the progress value of the progress bar
   public void Report(int value) { this.Value = value; }
}

MVVM

class SomeMVVM
{
   public async Task DoSomeExpensiveJob(IProgress<int> progressFeedback)
   {
       for(int i=0; i < 100; ++i)
       {
            progressFeedback.Report(i);
            await Task.Pause(1000);
       }
   }
}

that way, I can call DoSomeExpensiveWork, passing the ProgressBar control directly, to update the progress bar as the job progresses.

@rabbitism
Copy link
Contributor

that way, I can call DoSomeExpensiveWork, passing the ProgressBar control directly, to update the progress bar as the job progresses.

First of all, accessing visual element inside VM is bad practice.
Secondly you just need

class SomeMVVM
{
   public async Task DoSomeExpensiveJob(ProgressBar bar)
   {
       for(int i=0; i < 100; ++i)
       {
            bar.Value = i;
            await Task.Pause(1000);
       }
   }
}

@vpenades
Copy link
Author

DoSomeExpensiveJob(ProgressBar bar)

To do that you have to reference Avalonia in your MVVM project, with IProgress, you don't need to.

@rabbitism
Copy link
Contributor

passing the ProgressBar control directly

Hmm, that's you said passing the ProgressBar control directly, we usually update a number in ViewModel, and bind progressbar value to that value, no direct access.

@thevortexcloud
Copy link
Contributor
thevortexcloud commented Nov 15, 2024

I will also add that using a progress bar itself to track progress rather than the underlying value is very odd. As mentioned it also breaks MVVM by having the progress bar be passed to the view model, giving the view model knowledge of the view. Even if it's only an interface, it's still not great. Typically the view reads the view model, not the other way around.

@timunie
Copy link
Contributor
timunie commented Nov 16, 2024

@vpenades why not having a property Percentage which you update from your task and which is bound to the Progressbar as any other value?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants