如何从一个位于另一个Assembly中的BackgroundWorker数据绑定ProgressControl? [英] How to Databind a ProgressControl From a BackgroundWorker located in another Assembly?

查看:233
本文介绍了如何从一个位于另一个Assembly中的BackgroundWorker数据绑定ProgressControl?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Galasoft MVVM Toolkit的WPF作为客户端的多程序集项目。我想知道如何将ProgressControl的Value属性数据绑定到BackgroundWorker的ProgressChanged事件。



还有其他文章来处理这种情况;然而,他们只处理位于虚拟机中的工人。我的工作人员理想地位于DataService存储库中,它将执行大部分grunt工作,如下面的代码所示。



这是我得到的:



在View中,ProgressControl XAML是这样的:

 < ProgressBar最大值= {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}}>

绑定源位于另一个程序集中,如下所示:

  public class ConverterEntity:ViewModelBase 
{


public int ProgressValue
{
get
{
return _progressValue;
}
set
{
_progressValue = value;
RaisePropertyChanged(ProgressValuePropertyChanged);
}
}

回到App.xaml,我把参考必要的Windows资源,如下所示:

 < Application.Resources> 

< vc:ConverterEntity x:Key =ConverterEntity/>

显然,我可以看到尽管View xaml构建正常,但是没有使用vc引用...只是想知道它如何正确构建,即使ProgressBar不需要vc命名。



无论如何,ViewModel有一个绑定到一个运行此代码的命令:

  repo.ExtractAllZipArchiveSets(
(s,e)=>
...);

...这是一个执行咕噜码的存储库:

  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 =新的DiskFile(fileInfo.FullName);
ZipArchive zip = new ZipArchive(zipFile);
zip.CopyFilesTo(destinationFolder,true,true,* .r *);
}

...就是这样。



我不想让我的grunt代码在虚拟机中,因为我只是想从中调用并执行Action方法。存储库似乎是抽象出所有这些工作的正确的地方。



可能某种DependencyObject会做这个伎俩,而不是实例化的,私有领域使用像我一样如果我想提供ProgressControl的更新,那我该怎么做?



谢谢。

解决方案

似乎缺少一些信息,无论是关于 BackgroundWorker 类工作,或者来自外部项目的调用方法...这些都不会阻止您获得目标。



首先,我们确保你知道如何设置一个 BackgroundWorker 。请不要在此重复,请参阅我给予进度条的答案从后台工作人员更新停止问题,这里是StackOverflow。从这个例子来看,这里是 ProgressBar.Value 属性更新的位置:

  private void ProgressChanged(object sender,ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}

在您的情况下,如果您的数据绑定到 ProgressValue 属性到UI中的 ProgressBar.Value 属性,那么你可以这样做:

  private void ProgressChanged(object sender,ProgressChangedEventArgs e)
{
ProgressValue = e.ProgressPercentage;
}

到目前为止,好吗?好的,所以现在要从另一个程序集'/'连接你的 BackgroundWorker 。请注意,只要你有一个对象的实例,那么这个声明是真的并不重要。从我的例子来看,这里是我连接 BackgroundWorker 的地方:

  public TestView()
{
InitializeComponent();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.ProgressChanged + = ProgressChanged;
backgroundWorker.DoWork + = DoWork;
}

唯一的区别是您需要公开您的 BackgroundWorker 作为另一个程序集的一个属性,你可以这样使用:

  public TestView()
{
InitializeComponent();
classInOtherAssemblyReference.BackgroundWorker.WorkerReportsProgress = true;
classInOtherAssemblyReference.BackgroundWorker.ProgressChanged + = ProgressChanged;
classInOtherAssemblyReference.BackgroundWorker.DoWork + = DoWork;
}

为了澄清这一点,你需要一个类的实例你的UI代码/视图模型中的程序集( classInOtherAssemblyReference ),该类应该有一个 BackgroundWorker 类型为 BackgroundWorker


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.

解决方案

You seem to be missing some information, either on how the BackgroundWorker class works, or how calling methods from external projects... neither of these things would stop you from obtaining your goal.

First, let's make sure that you know how to set up a BackgroundWorker. Rather than repeat myself here, please refer to the answer that I gave to the Progress Bar update from Background worker stalling question, here on StackOverflow. From that example, here is where the ProgressBar.Value property gets updated:

private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
}

In your case, if you have data bound the ProgressValue property to the ProgressBar.Value property in the UI, then you'd do this:

private void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    ProgressValue = e.ProgressPercentage;
}

So far, so good? Ok, so now to 'wire up' your BackgroundWorker from another assembly. Please note that as long as you have an instance of your object, then it really doesn't matter where it was declared. From my example, here is where I hook up the BackgroundWorker:

public TestView()
{
    InitializeComponent();
    backgroundWorker.WorkerReportsProgress = true;
    backgroundWorker.ProgressChanged += ProgressChanged;
    backgroundWorker.DoWork += DoWork;
}

The only difference is that you would need to expose your BackgroundWorker as a property from the other assembly... you'd then use it something like this:

public TestView()
{
    InitializeComponent();
    classInOtherAssemblyReference.BackgroundWorker.WorkerReportsProgress = true;
    classInOtherAssemblyReference.BackgroundWorker.ProgressChanged += ProgressChanged;
    classInOtherAssemblyReference.BackgroundWorker.DoWork += DoWork;
}

To clarify this, you'd need an instance from a class from the other assembly (classInOtherAssemblyReference) in your UI code behind/view model and that class should have a BackgroundWorker property of type BackgroundWorker.

这篇关于如何从一个位于另一个Assembly中的BackgroundWorker数据绑定ProgressControl?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆