HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Access View from current/corresponding ViewModel

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
viewviewmodelcurrentfromcorrespondingaccess

Problem

Sometimes when developing a WPF application, I need to access a certain Window (View) from the corresponding ViewModel, to perform or fire a method like this for example:

//In the MainWindowViewModel
MainWindowView.Hide();


But that's not really easy, and even it violates MVVM because the ViewModel shouldn't know anything about the View, so I started doing this instead:

//In the MainWindowViewModel
Application.Current.MainWindow.Hide();


This becomes impractical when dealing with other Windows (Views):

//In the AnotherWindowView
Application.Current.Windows.OfType().First().Hide();


So I decided to make a solution, a helper class, in which, using a method, I give the ViewModel and I get back the corresponding View, using the DataContext of the View, the solution looks like this:

The Class:

public static class ViewsAccessibility
{
    public static Window GetCorresponingWindow(ViewModelBase viewModel)
    {
        var windowAccessibility = new WindowAccessibility(viewModel);
        return windowAccessibility.CorrespondanteWindow;
    }

    private class WindowAccessibility 
    {
        public Window CorrespondanteWindow { get; private set; }

        public WindowAccessibility(ViewModelBase viewModel)
        {
            var windows = Application.Current.Windows.OfType();
            CorrespondanteWindow = (from window in windows
                                      where window.DataContext.Equals(viewModel)
                                      select window).First();
        }
    }
}


The use:

//In the MainWindowViewModel
ViewsAccessibility.GetCorresponingWindow(this).Hide();


Is this a good practice and does it violate MVVM or not?

Solution

You have multiple options

a. Use an event Aggregator where publish the message from the viewmodel and subscribe from view. see prism documentation for event aggregators:here is sample code

//view will subscribe from this message 
_aggregator.GetEvent().Subscribe(CloseAction);

 private void CloseAction(string s) { //do your logic }
 //view model will pubilsh this request 
 _aggregator.GetEvent().Publish(output);


b. create an interface named as IView and implement it in your view , pass the instance of IView to data context of the view

public partial class Shell : Window ,IView
{
    public Shell()
    {
        InitializeComponent();
        this.DataContext.View = this;
    }

    public void CloseShell()
    {

    }
}

public interface IView
{
    void CloseShell();
}


by using this you have only a reference of interface will be there in viewmodel . but not the whole view itself

Code Snippets

//view will subscribe from this message 
_aggregator.GetEvent<CloseEvent>().Subscribe(CloseAction);

 private void CloseAction(string s) { //do your logic }
 //view model will pubilsh this request 
 _aggregator.GetEvent<CloseEvent>().Publish(output);
public partial class Shell : Window ,IView
{
    public Shell()
    {
        InitializeComponent();
        this.DataContext.View = this;
    }

    public void CloseShell()
    {

    }
}

public interface IView
{
    void CloseShell();
}

Context

StackExchange Code Review Q#58240, answer score: 3

Revisions (0)

No revisions yet.