简体   繁体   中英

Callback from ViewModel to View

My View calls a method in ViewModel to Fetch Data. After fetching the data, I build my View(Grid) based on the data that got back from the ViewModel.

getData() Method in the View Model runs in a BackgroundWorker thread. Now my question is how do I get back to View after the View is done fetching all the data?

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


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

     }

From the View, I will be calling

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

I want the BuildUI() method to be executed only after the VM.getData() is executed fully and in turn is done with Refresh() method as well which is what has the Data I need to be able to build the UI Dynamically.


This is what I am going to do. Please correct me if this is not right approach.

In the View code behind,

  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.
      }

You should retrieve the data once the BackgroundWorker has completed its work. Your view model should implement the INotifyPropertyChanged interface and expose the data through a property that the view binds to. The view model can then notify the view when the data is available (ie the BackgroundWorker has completed its work).

One approach is to use messaging. That is, register your message on the view, then send a message from the view model to the view, when this message is received then you could call your BuildUI method.

For example, if you were using the MvvmLight framework, here's one way of passing back an error message to show up in a dialog. You might not want to show a dialog (I had this code on hand), but the process is the same, it's just a different message type to register and send.

ViewModel:

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.          
    }
}

View:

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.
        });
     }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM