0

A little while ago, I wrote this SO post looking for a good way to handle UI and business layer interaction, and I liked the answer which was to use the MVVM pattern.

So I did so quite successfully, but I'm a bit stuck with a problem using this pattern. Indeed, in some part of my UI, one of my buttons is supposed to open a dialog with the details of an item displayed in a ListView.

I saw this SO post asking about the same question, but I didn't quite understand the answer and I wonder if it is suitable in my case. The idea was to use the Unity framework and to call the window associated with the view in the repository using App.Container.Resolve<MyChildView>().ShowDialog(), for example.

However, my problem is that I have implemented the ViewModels in project separate from the UI client project. I did this in order to be able to use the VMs from another client if need at a later stage of the project. First question, was that a wrong implementation of the pattern?

Second question, as my ViewModels project isn't actually in the client's project, and hence I do not have access to the App global variable. Therefore, I don't think I can use the solution I found in the previously mentioned post. Is there any workaround?

Community
  • 1
  • 1
SRKX
  • 1,806
  • 1
  • 21
  • 42

2 Answers2

1

1) Your implementation is not wrong at all. I regularly separate UI, VM, and models into separate assemblies.

2) As you mentioned, it isn't appropriate to reference App within a VM. Consider App a "UI class" and treat it as such. Have you considered injecting the appropriate UnityContainer into your VM?

If injecting the container isn't an option for you, think about adding a controller to your solution or using the Mediator pattern as suggested by other answers in that SO post you mentioned.

Community
  • 1
  • 1
RMart
  • 548
  • 1
  • 5
  • 20
  • As discussed when in the other post, using a controller "breaks" the MVVM pattern as long as you give a reference of the view to the modelview right? As for the Unity container, how could I inject it to the MV without referecing the views? – SRKX Sep 26 '11 at 21:53
  • @SRKX , I disagree that a controller breaks MVVM. I usually add a Controller class to my UI assembly which implements an interface (IController defined in the VM assembly or common assembly). MY VMs get an IController injected. You don't want to expose any members on your Controller that would create a dependency on the UI assembly. For example, don't expose a `MyChildView` member, instead expose a method that does the work you'd like. – RMart Sep 27 '11 at 13:12
  • If you need to go extreme with decoupling and don't like the idea of a Controller that is coupled to concrete UI classes, consider implementing interfaces on your views. There's nothing wrong with a VM or Controller that executes `_injectedContainter.Resolve().ShowDialog()` . – RMart Sep 27 '11 at 13:20
0

Try this. Set up a new thread, initialize and show your window (You can also use ShowDialog() instead of Show()), and then convert the thread to a UI thread by calling Dispatcher.Run() which will block until the window is closed. Then, afterwards, you can handle the dialog result however you want.

new Thread(() =>
{
    MyDialogWindow m = new MyDialogWindow();
    m.ShowDialog();
    Dispatcher.Run();
    // Handle dialog result here.
}).Start();

Be sure to add an event in your dialog for when you close the window, to have the Dispatcher stop. Add this to your constructor of the dialog:

Closed += (_,__) => Dispatcher.InvokeShutdown();
qJake
  • 16,821
  • 17
  • 83
  • 135
  • 1
    But this would mean referencibg a view from within the VM, which is countrary to the pattern's idea isn't it? – SRKX Sep 26 '11 at 20:29
  • Don't reference it from the viewmodel. Create a separate class to do this, that returns the value(s) from the dialog window. – qJake Sep 26 '11 at 23:04