2011-03-22 70 views
1

我有一个循环访问IEnumerable集合的方法,并将它们传递给另一个方法。例如:如何使用IEnumerable实现进度?

void Run (object item) 
{ 
    foreach(var method in this.Methods) 
     method (item); 
) 

我该如何实现进度条中反映的进度排序?我可以很容易地做到这一点,如果它是直接编码在这种方法,但这种方法是包含在ViewModel以外的类型,我当然可以调用。

我只是不知道如何实现它,并从该方法得到它,反映UI的变化,将它传递给ViewModel

任何想法?

+0

不要让这个递归于你。如果'Run'在'this.Methods'里面,你就会有一个装满蜂蜡的盘子! – corsiKa 2011-03-22 21:44:28

+0

哈哈,你是什么意思? this.Methods包含来自许多不同静态类的方法,但不包含它自己。 – 2011-03-22 21:45:20

回答

2

我会通过使用以下事件来解决这个问题。

public class ViewModel : ViewModelBase 
{ 
    private int m_CurrentProgress; 
    private int m_MethodCount; 

    // Bind this to the progress bar 
    public int CurrentProgress 
    { 
     get { return m_CurrentProgress; } 
     set 
     { 
      m_CurrentProgress = value; 
      OnPropertyChanged("CurrentProgress"); 
     } 
    } 

    // Bind this to the progress bar 
    public int MethodCount 
    { 
     get { return m_MethodCount; } 
     set 
     { 
      m_MethodCount = value; 
      OnPropertyChanged("MethodCount"); 
     } 
    } 

    private void MethodExecuted(object sender, EventArgs e) 
    { 
     CurrentProgress++; 
    } 

    public void Run() 
    { 
     var c = new ExternalClass(); 
     MethodCount = c.Methods.Count; 
     c.MethodExecuted += MethodExecuted; 

     c.Run(null); 
    } 
} 

public class ExternalClass 
{ 
    public List<object> Methods { get; set; } 

    public event EventHandler<EventArgs> MethodExecuted; 

    public void InvokeMethodExecuted(EventArgs e) 
    { 
     EventHandler<EventArgs> handler = MethodExecuted; 
     if (handler != null) 
     { 
      handler(this, e); 
     } 
    } 

    public void Run(object item) 
    { 
     foreach (var method in Methods) 
     { 
      method(item); 

      InvokeMethodExecuted(null); 
     } 
    } 
} 
+0

谢谢btw ExternalClass是静态的。这很重要吗?我可以转换它,但不知道这个想法是否仍然有效。 – 2011-03-22 21:55:07

+0

理想情况下,类将被实例化,这样你就不会有一个静态事件,如果你在不同的线程上多次运行这些东西,那么这个静态事件可能会变得混乱,如果不是这种情况,那么你可以使它变成静态的。不应该是一个问题。 – bic 2011-03-22 21:57:17

2

我最终做的是传递用于报告进度的委托。这提供了非常好的解耦。该委托可以实现为一个lambda函数,它可以直接设置表单上的进度。

void Run (object item, Action<float> progress) 
{ 
    int total = MethodCollection.Count; 
    int index = 0; 
    foreach(var method in MethodCollection) 
    { 
     method (item); 
     progress(index/(float)total); 
    } 
) 

对于长时间运行的任务,我会做这个使用BackgroundWorker的,它具有内置挂钩报告进度一个单独的线程。

+0

你能告诉我这将如何使用?我正在尝试查看如何在调用者中指定Action,仅供想法。 – 2011-03-22 21:47:15