Hello all,
I've been trying to implement a progress bar on a dock pane that increments as a function in a separate class downloads a list of GeoTiffs using HttpClient.
I've successfully got this to work using the approach provided in the code sample Overlay3D.
However, unlike this example, my list of tasks I want to increment occurs in a separate function outside of the dock pane, and I'm not sure how to pass the information from that function back to the dock pane.
Any advice is welcome. I have provided a cut down code example below of my current setup, the comments should show where I am getting stuck:
XAML progress bar, with two bindings (MaxProgressValue and Progress Value) back to dock pane view model.
<!-- Progress bar-->
<ProgressBar Name="PrgProgressBar"
Grid.Column="0"
Margin="0,0,5,0"
Height = "10"
HorizontalAlignment="Stretch"
Minimum="1"
Maximum="{Binding Path=MaxProgressValue, Mode=OneWay}"
Value="{Binding Path=ProgressValue, Mode=OneWay}"
IsIndeterminate="False">
</ProgressBar>
ViewModel related to progress bar, with a button to call a function to download geotiffs.
// Getter, Setter for progress bar
private double _maxProgressValue = 100;
public double MaxProgressValue
{
get { return _maxProgressValue; }
set { SetProperty(ref _maxProgressValue, value, () => MaxProgressValue); }
}
// Update progress bar method (based on Overlay3D)
private int _iProgressValue = -1;
private int _iMaxProgressValue = -1;
private void ProgressUpdate(int iProgressValue, int iMaxProgressValue)
{
if (System.Windows.Application.Current.Dispatcher.CheckAccess())
{
if (_iMaxProgressValue != iMaxProgressValue)
{
MaxProgressValue = iMaxProgressValue;
}
if (_iProgressValue != iProgressValue)
{
ProgressValue = iProgressValue;
}
}
else
{
ProApp.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)(() => {
if (_iMaxProgressValue != iMaxProgressValue)
{
MaxProgressValue = iMaxProgressValue;
}
if (_iProgressValue != iProgressValue)
{
ProgressValue = iProgressValue;
}
}));
}
}
// Button on dock panel to run download function
public ICommand CmdRun
{
get
{
return new RelayCommand(async () =>
{
// Excluded various things
// ...
// Initialise data structure STAC that contains urls and functions
Stac stac = new Stac(...)
// Reset progressor value and maximum value
ProgressUpdate(1, stac.Result.Features.Count);
// Start queued task and download geotifs
await QueuedTask.Run(() =>
{
// Begin download tifs loop
// How do I monitor progession?
// Pass a progressor variable via IProgress?
await stac.DownloadFeaturesAsync(assets, outputFolder);
});
}
}
Stac class for DownloadFeatureAsync.
public async Task DownloadFeaturesAsync(List<string> assetNames, string outputFolder)
{
// Some uninteresting work...
// ...
// Iterate dates in STAC query and download tif to folder
foreach (string date in dates)
{
// Open a HTTP client
var client = new HttpClient();
// Create a list of downloader tasks
int i = 0; // test
var tasks = new List<Task>();
foreach (var item in items)
{
string date = item.Key;
string url = item.Value[0];
string filename = item.Value[1];
tasks.Add(Task.Run(async () =>
{
// Do some things...
// Query URL and ensure success
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
// Download file to output folder
using (FileStream fs = new FileStream(filepath, FileMode.CreateNew))
{
await response.Content.CopyToAsync(fs);
}
// Increment progress bar... how...?!
// ...
}));
}
// Run all download tasks
await Task.WhenAll(tasks);
}