从ViewModel回调到视图

从ViewModel回调到视图

问题描述:

我的视图调用ViewModel中的方法来获取数据。获取数据后,我根据从ViewModel返回的数据构建View(Grid)。从ViewModel回调到视图

getData()View Model中的方法在BackgroundWorker线程中运行。现在我的问题是如何在View完成获取所有数据后返回View?

ViewModel 
    { 
     getData() 
     { 
      WorkerMethods() 
      WorkerCompletedMethod() 
      { 
       Refresh() 
      } 
     } 


     Refresh() 
     { 
      WorkerMethod() 
      WorkerCompleted() 
      { 
       data - Retrieved. 
       This is where all the calls are really DONE 
      } 
     } 

    } 

从查看,我会打电话

View() 
{ 
    VM.getData() 
    //Before I call this method, I want to make sure Refresh() is completed 
    BuildUI() 
} 

我只想要VM.getData(后要执行的BuildUI()方法)完全执行,又与刷新完成()方法,这也是我需要能够动态构建UI的数据。


这就是我要做的。请纠正我,如果这是不正确的做法。

在后面的视图代码,

View 
    { 

     public delegate void DelegateRefresh(); 
     Init() 
     { 
      DelegateRefresh fetcher = RefreshData; 
      fetcher.BeginInvoke(null, null); 
     } 


     public void RefreshData() 
     { 
     _viewModel.GetData(); 
     **while (_viewModel.IsBusy)** 
     {    
      continue; 
     } 
     BuildUI(); 
     } 

     BuildUI() 
     { 
     //Code to build the UI Dynamically using the data from VM. 
     } 

你应该检索数据一旦BackgroundWorker已完成其工作。您的视图模型应该实现INotifyPropertyChanged接口并通过视图绑定的属性公开数据。当数据可用时,视图模型可以通知视图(即BackgroundWorker已完成其工作)。

+0

你需要明确具体的关于你的要求,否则你不会得到有用的答案。请更新您的问题。 – Bernard 2012-08-10 02:20:00

+0

对不起,我更新了我的oroginal Post,请让我知道如果它不明确。 – nmgans 2012-08-10 02:29:36

一种方法是使用消息传递。也就是说,在视图中注册消息,然后从视图模型向视图发送消息,当收到此消息时,您可以调用BuildUI方法。

例如,如果您使用的是MvvmLight框架,以下是一种传回错误消息以显示在对话框中的方法。您可能不想显示对话框(手头上有此代码),但过程相同,只是用于注册和发送的不同消息类型。

视图模型:

public class ErrorMessage : DialogMessage 
{ 
    // See MvvmLight docs for more details, I've omitted constructor(s) 

    /// <summary> 
    /// Registers the specified recipient. 
    /// </summary> 
    /// <param name="recipient">The recipient of the message.</param> 
    /// <param name="action">The action to perform when a message is sent.</param> 
    public static void Register(object recipient, Action<ErrorMessage> action) 
    { 
     Messenger.Default.Register<ErrorMessage>(recipient, action); 
    } 

    /// <summary> 
    /// Sends error dialog message to all registered recipients. 
    /// </summary> 
    public void Send() 
    { 
     Messenger.Default.Send<ErrorMessage>(this); 
    } 
} 

public class SomeViewModel : ViewModelBase 
{ 
    public void SendErrorMessage(string message) 
    { 
     var errorMessage = new ErrorMessage(message); 
     errorMessage.Send(); 
     // Or in your case, when the background worker is completed.   
    } 
} 

查看:

public partial class SomeView : Window 
{ 
    public SomeView() 
    { 
     InitializeComponent(); 
     ErrorMessage.Register(this, msg => 
     { 
      MessageBoxResult result = MessageBox.Show(msg.Content, msg.Caption, 
       msg.Button, msg.Icon, msg.DefaultResult, msg.Options); 
      msg.ProcessCallback(result); 
      // Or in your case, invoke BuildUI() method. 
     }); 
    } 
+0

感谢您的建议。尽管我没有使用MvvmLight框架。我们正在使用PRISM。无论如何,这是我最终做的。我创建了一个委托方法,并在其上调用了BeginInvoke()。在委托方法内部,我将检查ViewModel中的IsBusy属性是否为true,一旦它为false,我知道我已完成View Model中的工作。将在原始帖子中发布代码。 – nmgans 2012-08-10 14:05:45

+0

这将工作正常。我使用'IsWaiting'和转换器为鼠标光标做类似的操作。 – si618 2012-08-13 01:51:58