-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Comments
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. |
@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. |
First of all, accessing visual element inside VM is bad practice. class SomeMVVM
{
public async Task DoSomeExpensiveJob(ProgressBar bar)
{
for(int i=0; i < 100; ++i)
{
bar.Value = i;
await Task.Pause(1000);
}
}
} |
To do that you have to reference Avalonia in your MVVM project, with IProgress, you don't need to. |
Hmm, that's you said |
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. |
@vpenades why not having a property Percentage which you update from your task and which is bound to the Progressbar as any other value? |
Everybody answering me it's assuming I have full control over the code, it's outdated, closed source libraries I'm calling. Also everybody is assuming mvvm while I'm actually doing this in code behind, that is, calling a background task that takes a iprogress interface as a parameter, on an event So that forces me to write a proxy object that implements iprogrees, so i can pass it as an argument, and updates the progressbar |
Well you did give an MVVM example.
I don't see a problem with this. If you really want to do this, then this is the correct approach. With that said: You could even rewrite your own app's code to use MVVM, even with closed source code you can't modify. After all a view model is meant to wrap a model and not do very much on its own. You just need to pass a In any case, there are some possible technical problems with this. Avalonia/src/Avalonia.Controls/ProgressBar.cs Lines 224 to 231 in a5f5b8f
The actual value of a progress bar is also a double. Avalonia/src/Avalonia.Controls/Primitives/RangeBase.cs Lines 111 to 118 in a5f5b8f
Your example explicitly shows an integer. Assuming that is what your third party code wants, then you might need to wrap it regardless. Also what would the report value even be: This is also going to encourage "bad" code, especially for people using MVVM. As they will be tempted to just directly pass a reference to the progress bar to the VM instead of using the existing binding system which solves this problem already. |
Note that even if you have a special case with existing code or other restraints, we cannot change the framework to accommodate this. It's against the MVVM design principles that the framework does need to follow here. If you want to deviate that's fine but it must be in your app only. I think this should be closed as by design. |
My point of view is this:
So I was not seeing any harm for ProgressBar to implement an IProgress interface. To me, IProgress is almost an abstraction of a progress bar. Implementing it does not affect the current behavior and ony adds new ways of using the ProgressBar, its up to developers to use it or not. But certainly I failed to make my point, so closing. |
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
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
Describe alternatives you've considered
Right now I'm using a wrapper:
Additional context
.Net
Also has these types:
IProgress<T>
interfaceProgress<T>
classSystem.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
The text was updated successfully, but these errors were encountered: