I have a multi-assembly project with WPF as the client using the Galasoft MVVM Toolkit. I would like to know how to databind a ProgressControl's "Value" property to a BackgroundWorker's ProgressChanged event.
There are other articles that deal with this situation; however, they only deal with the Worker being situated in the VM. My Worker is ideally located in the DataService Repository which does the bulk of the grunt work as will be shown in the code below.
Here's what I got:
In the View, the ProgressControl XAML is this:
<ProgressBar Maximum="{Binding NumberOfPublications}"
Minimum="0"
Height="50"
Margin="10"
Value="{Binding Source={StaticResource ConverterEntity},Path=ProgressValue, Mode=OneWay}"
Visibility="{Binding Source={StaticResource ConverterEntity}, Path=IsLengthyOperation, Converter={StaticResource Bool2InverseVisibility}}">
The Binding Source is in another Assembly, like this:
public class ConverterEntity : ViewModelBase
{
.
.
public int ProgressValue
{
get
{
return _progressValue;
}
set
{
_progressValue = value;
RaisePropertyChanged( ProgressValuePropertyChanged );
}
}
Back in the App.xaml, I have put the reference necessary in a Windows Resource, as shown:
<Application.Resources>
<vc:ConverterEntity x:Key="ConverterEntity" />
Clearly, I can see that although the View xaml builds fine, the "vc" reference is not used... just wondering how it builds correctly, even though the ProgressBar doesn't need the "vc" nomenclature.
Anyways, The ViewModel has a button that is bound to a command that runs this code:
repo.ExtractAllZipArchiveSets(
( s , e ) =>
... );
... which is a Repository that executes the grunt code:
public void ExtractAllZipArchiveSets( Action<ObservableCollection<Publication>
, Exception> callback , string rootDirectory ) {
.
.
DirectoryInfo dirInfo = new DirectoryInfo( rootDirectory );
BackgroundWorker worker = null;
Thread.Sleep( 2000 );
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler( ExtractZipFile );
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler( AddPublicationToBeProcessed );
worker.ProgressChanged += ProgressChanged;
worker.RunWorkerAsync( zipInfo );
worker.WorkerReportsProgress = true;
worker.ReportProgress( (dirCounter +=1 ) * 10);
.
.
}
public void ProgressChanged( object sender , ProgressChangedEventArgs e )
{
//ConverterEntity entity = new ConverterEntity();
//entity.ProgressValue = e.ProgressPercentage;
}
private void AddPublicationToBeProcessed(object sender, RunWorkerCompletedEventArgs e)
{
}
private void ExtractZipFile( object sender , DoWorkEventArgs e )
{
FileInfo fileInfo = new FileInfo( ( e.Argument as FileSystemInfo ).FullName );
DiskFolder destinationFolder = new DiskFolder( fileInfo.Directory.ToString() );
DiskFile zipFile = new DiskFile( fileInfo.FullName );
ZipArchive zip = new ZipArchive( zipFile );
zip.CopyFilesTo( destinationFolder , true , true , "*.r*" );
}
... and that's it.
I didn't want my grunt code in the VM, as I just want to call and execute Action methods from it. The Repository seems like the proper place to abstract away all this work.
Probably some kind of DependencyObject would do the trick, as opposed the instanced, and private field used like I have it which clearly won't work.
However, if I want to provide updates to the ProgressControl, how would I do that?
Thank You.