2
votes

First I must apologies if this is simple. I am very new with WPF and MVVM and I want to make sure I am not violating any WPF or MVVM concept. Also, for the wordy explanation below (trying to give all details):

I am currently referencing to an Assembly dll with all the business logic or service layer (service classes, entity classes, data operations, etc).

This is used in others traditional Windows Forms applications. I am now creating a new desktop WPF application (early stage) and I must consume the same assembly.

I created a main windows with menu, status bar, etc. and its ViewModel (Lets called _mainViewModel).

I created another simple windows with its own ViewModel object (Lets called _abcViewModel). Windows objects/controls are binding fine in child view. This works great and so far I am happy with it.

The _abcViewModel consumes logic from the assembly that can retrieve some messages using traditional delegates and event handlers.

Now, my intention is to bind the messages coming from those events to the Main Window StatusBar object which is bind to _mainWindowViewModel.StatusBarItemMessage. How can I do that?

I found from another stackoverflow post (: How to access WPF MainWindow Controls from my own .cs file) that you can access main window objects by using something like: ((MainWindow)System.Windows.Application.Current.MainWindow)._mainWindowViewModel.StatusBarMessage = args.Message;

I subscribe those DLL events handlers within _abcViewModel:

    private void SubscribeBusinessLogicEvents()
    {
        _SPPIDDrawingWPFService.PidToolBoxInfoEvent += new SPPIDDrawingWPFService.PidToolBoxInfoEventHandler(PidToolBoxInfoEvent);
        _SPPIDDrawingWPFService.PidToolBoxErrorEvent += new SPPIDDrawingWPFService.PidToolBoxErrorEventHandler(PidToolBoxErrorEvent);
    }


    private void UnsubscribeBusinessLogicEvents()
    {
        _SPPIDDrawingWPFService.PidToolBoxInfoEvent -= PidToolBoxInfoEvent;
        _SPPIDDrawingWPFService.PidToolBoxErrorEvent -= PidToolBoxErrorEvent;

    }


    internal void PidToolBoxErrorEvent(object sender, PidToolBoxEventArg args)
    {
        App.WriteLocalErrorLogFile(args);
    }


    internal void PidToolBoxInfoEvent(object sender, PidToolBoxEventArg args)
    {
        //Is this correct? Can I change Main Windows view model from here?
        ((MainWindow)System.Windows.Application.Current.MainWindow)._mainWindowViewModel.StatusBarItemMessage = args.Message;
        if (args.OptionalPopUpFlag)
        {
            //
        }
        App.WriteWoodEngSysToolBoxErrorLog(args);
    }

Is this the correct way? Is accessing ViewModels from other ViewModels breaking the concept of Model–view–viewmodel or MVVM?.

How can I update main Window Statusbar control from operations that are executed from child windows. I do not want to end up with a massive ViewModel object for all windows.

Any help/advise would be greatly appreciated. Thanks

1

1 Answers

1
votes

Look into Event Aggregation. Your MainWindowViewmodel should subscribe to "events" that your AbcViewModel broadcasts. This will decouple your AbcViewModel from your MainWindowViewModel.

Prism is a library that implements this pattern. The library may be overkill for your needs, but you can easily implement your own system.

Your usage may look like something similar:

AbcViewModel.cs

 internal void PidToolBoxInfoEvent(object sender, PidToolBoxEventArg args)
 {
        _eventAggregator.GetEvent<PidToolBoxUpdateEvent>().Publish(args);

        App.WriteWoodEngSysToolBoxErrorLog(args);
  }

MainWindowViewModel.cs

public class MainWindowViewModel
{
    public MainWindowViewModel(IEventAggregator ea)
    {
        // You may need to subscribe on the UI thread. 
        // If so, use: Subscribe(..., ThreadOption.UIThread) 
        ea.GetEvent<PidToolBoxUpdateEvent>().Subscribe(UpdateStatusBar);
    }

    void UpdateStatusBar(PidToolBoxEventArg pidEventArgs)
    {
        //implement logic
    }
}