0

I am developing a MVVM WPF application. I can tell you the code looks cleaner but some menial tasks have become a big trouble for me.

A good example is to show OpenFileDialog or heck even a MessageBox from the ModelViewer class. I know how to use the RelayCommand but I cannot make OpenFileDialog show. I read in the SO that it would require application service. What is application service?

I cannot find any tutorial on this. Can someone explain it to me with some example as well? I know it is something related to interfaces...

Haikal Nashuha
  • 2,958
  • 7
  • 44
  • 67
  • I think the answer can be found [here](http://stackoverflow.com/questions/925017/what-exactly-are-wpf-services) – Teddy Bo Jan 14 '14 at 06:35
  • @TeddyBo There is no tutorial whatsoever there, and it makes it hard to grasp on the concept. Can you show me a simple example? – Haikal Nashuha Jan 14 '14 at 06:37

2 Answers2

3

"Service" is a general purpose abstraction, that allows you to isolate some portion of code from another parts of application.

Usually, in WPF/MVVM world, "service" consists of at least three items:

  • service interface;
  • one "real" service implementation, which does all the work;
  • one "fake" service implementation for unit-testing purposes.

Service groups a bunch of related methods. There could be "dialog services" (show dialogs), "data services" (get data from data source, save data to data source), etc. You may think about "service" as of about the way to link your view models with outer world.

For example, WPF service, which purpose is to show some typical dialogs, will have interface like this:

public interface IDialogService
{
    void ShowAboutBox(AboutBoxSettings settings);
    MessageBoxResult ShowMessageBox(MessageBoxSettings settings);
    bool? ShowSaveFileDialog(FileDialogSettings settings);
    bool? ShowOpenFileDialog(FileDialogSettings settings);
}

Its "real" implementation will call methods from appropriate classes to show dialogs:

public sealed class DialogService : IDialogService
{
    // ...

    public void ShowMessageBox(MessageBoxSettings settings)
    {
        return MessageBox.Show(/* ... */);
    }

    public bool? ShowOpenFileDialog(FileDialogSettings settings)
    {
        var dialog = new OpenFileDialog();

        // ...

        return dialog.ShowDialog();
    }

    // ...
}

Again, usually, view models access services in two ways:

Both ways assumes, that view models never access services, using particular implementations. Instead of this, they are asking service locator or DI-container to provide them available implementation of some service contract:

// getting service through service locator
var dialogService = ServiceLocator.GetService<IDialogService>();

or

// inject service dependency with MEF container
[Import]
private IDialogService dialogService;

You should choose the way to access services yourself, but, ultimately, you'll need to read about several existing implementations of service locators or DI-containers.

And finally, what do you need all this stuff for? Why just don't show message boxes and work with database from view models?

The answer is simple.

The first. With services your view models contains only that code, which is responsible to interact with the view. You have well-structured, decoupled code, where one set of classes interacts with views, another set - with WPF presentation subsystem, another - with database or web-services, etc. Since view model doesn't depend on service implementation, you can change implementation code easily (for example, fix a bug) without affecting view model(s).

The second. You can mock your "real" service with test one, and write unit test for the view model.

Dennis
  • 37,026
  • 10
  • 82
  • 150
  • From what I came across the net, apparently the View Model should not have any interaction with the View, so if I call the dialog directly from View Models, somehow this would violate the MVVM design concept. To be honest, MVVM is confusing lol! – Haikal Nashuha Jan 14 '14 at 08:55
  • With "interaction" I mean, that VM prepares data, which is bound to the view. You shouldn't show dialogs directly, and yes, services is the way to do it. – Dennis Jan 14 '14 at 09:10
1

As far as I know there is no OpenFileDialog for WPF so one from winform should be used. Something like this:

 var fileName = Application.Current.Dispatcher.Invoke<string>(() =>
     {
         var openFileDialog = new OpenFileDialog();
         openFileDialog.ShowDialog();
         return openFileDialog.FileName;
     });

As I've understood under application services they mean the isolation of this code in some class that is passed to view models using dependency injections.

Instead of using message boxes it is easier to use TextBlock (or some border with children) that is placed over all other controls on the form and is unvisible by default.

Teddy Bo
  • 679
  • 8
  • 19
  • For the messagebox, I did exactly what you suggested. But for the OpenFileDialog, I am stuck with this one. – Haikal Nashuha Jan 14 '14 at 07:03
  • The code above can be used directly in a relay command of a view model or as I mentioned encapsulated in some class. – Teddy Bo Jan 14 '14 at 07:24
  • I followed this one instead of creating service. MVVM is surprisingly stupid in handling menial tasks and consume a lot of energy for that. – Haikal Nashuha Jan 14 '14 at 07:37