MVVM ViewModel and static methods - c#

I try to rewrite my Application using the MVVM pattern.
I have a window to show related documents for different objects with static methods like this:
public partial class ShowRelatedDocuments : Window
{
private ShowRelatedDocuments()
{
InitializeComponent();
}
public static void ShowRelatedDocument(A objA)
{
ShowRelatedDocuments srd = new ShowRelatedDocuments();
srd.HandleA(objA);
srd.ShowDialog();
}
public static void ShowRelatedDocument(B objB)
{
ShowRelatedDocuments srd = new ShowRelatedDocuments();
srd.HandleB(objB);
srd.ShowDialog();
}}
Is there a way to keep these methods static like this?
ShowRelatedDocumentsVM.ShowRelatedDocument(A objA);
ShowRelatedDocumentsVM.ShowRelatedDocument(B objB);
I didn't find anything about ViewModels and static methods. Can a VM create a instance of itself and show his View (here a window)?
Or is the better way to pass the objects as parameter to the constructor of the VM like this?
public ShowRelatedDocumentsVM(A objA)
{
HandleA(obj A)
ShowRelatedDocuments srd = new ShowRelatedDocuments();
srd.DataContext = this;
srd.ShowDialog();
}
public ShowRelatedDocumentsVM(B objB)
{
HandleB(objB);
ShowRelatedDocuments srd = new ShowRelatedDocuments();
srd.DataContext = this;
srd.ShowDialog();
}
Or are both ways wrong, cause i breach the MVVM pattern due creating the view in the viewmodel?
Thx in advance.

How to display dialogs is one of the areas of MVVM that is not immediately clear, and there are a number of ways the behaviour can be achieved.
I would suggest using either a mediator (as described here) or by injecting a dependency on the view model that controls dialogs:
interface IDialogService
{
void ShowRelatedDocumentsA(A a);
}
...
class MyViewModel
{
private IDialogService _dialogService
public MyViewModel(IDialogService dialogService) { _dialogService = dialogService; }
public void DoSomething()
{
_dialogService.ShowDialog(...);
}
}
Either of these can will permit you to control the creation of the view outside of the view model, and will remove any explicit references from VM -> V.

Related

Same command for multiple views

I have two identical views View1.xaml and View2.xaml and they both have a button button1 and a textfield textfield1. The idea is that when you press the button, the corresponding textfield is filled with some information. Both views use the same method for filling in the textfield (the views are literally identical in that sense).
My question is: how to write generic code using OOP principles and not break the MVVM pattern? My current way of performing this with RelayCommand:
The same code for ViewModel1 and ViewModel2:
public RelayCommand ButtonCommand { get; private set; }
#Constructor
ButtonCommand = new RelayCommand(ExecuteButtonCommand, CanExecuteButtonCommand);
#EndConstructor
private void ExecuteButtonCommand(object message)
{
//Some method to fill the corresponding textfield
}
private bool CanExecuteButtonCommand(object message)
{
return true;
}
Binding for the button in View1.xaml and View2.xaml:
<Button Command="{Binding Path=ButtonCommand, Mode=OneWay}" />
This is bad, because I have to write the same code for both ViewModels. I was trying to make a class ButtonCommand which inherits from RelayCommand, but because not every view will have this functionality, I can't achieve it using this method.
Rather than having a "Base" view model and two derived view models, have your two view models both use the same code defined elsewhere (ideally, both calling the same interface, injected with dependency injection).
This is the Composition over Inheritance principle.
When you're writing your tests, test that both view models call the interface, and test that the implementation of that interface does what it is supposed to do once.
This way, not only can you avoid writing your code twice, you can also avoid testing it twice, and it also allows you to follow other principles like the single responsibility principle.
This could be an way to go:
1 - Create a base viewmodel class:
public class YourBaseViewModel
{
public Object YourBaseProperty{get; set;}
public RelayCommand ButtonCommand { get; private set; }
private void ExecuteButtonCommand(object message)
{
//Some method to fill the corresponding textfield
}
private bool CanExecuteButtonCommand(object message)
{
return true;
}
}
2 - Inherit from the base viewmodel:
public class ViewModel1:YourBaseViewModel
{
// ....
}
public class ViewModel2:YourBaseViewModel
{
// ....
}
EDIT:
If you have another base class you could do:
public class YourBaseViewModel:YourReallyBaseViewModel
{
// ....
}
public class ViewModel1:YourBaseViewModel
{
// ....
}
public class ViewModel2:YourBaseViewModel
{
// ....
}
This is an XY problem. You're asking for a way to solve Y (not duplicate the same ButtonCommand but in actuality), your problem is X (you already have duplication in your code)
I have two identical views View1.xaml and View2.xaml
I'd like to add, that you've also stated you don't have only two identical views, there's more.
The best way to resolve this is to have a parent ParentViewModel that can construct the child ViewModels
So first, we'll need an interface for the child view model
IMyViewModel
public interface IMyViewModel
{
void Load();
}
Next, the implementation
MyViewModel
public class MyViewModel : ViewModelBase, IMyViewModel
{
public MainViewModel()
{
ButtonCommand = new RelayCommand(ExecuteButtonCommand, CanExecuteButtonCommand);
}
public RelayCommand ButtonCommand { get; private set; }
public void Load()
{
//Example load logic
InvalidateCommands();
}
private void InvalidateCommands()
{
ButtonCommand.RaiseCanExecuteChanged();
}
private void ExecuteButtonCommand(object message)
{
//Some method to fill the corresponding textfield
}
private bool CanExecuteButtonCommand(object message)
{
return true;
}
}
And lastly the ParentViewModel which has the responsibility of creating the view models. Please note, I did not tell it WHEN to create the ViewModels, I will leave that up to you.
Parent View Model
public class ParentViewModel : ViewModelBase
{
private Func<IMyViewModel> _myVmCreator;
public ParentViewModel(Func<IMyViewModel> myVmCreator)
{
_friendEditVmCreator = friendEditVmCreator;
}
public ObservableCollection<IMyViewModel> MyViewModels { get; private set; }
private IMyViewModel CreateAndLoadMyViewModel()
{
var myVm = _myVmCreator();
MyViewModels.Add(myVm);
myVm.Load();
return myVm;
}
}
This will allow you to create any number of MyViewModels, or any other type of ViewModel as long as it implements IMyViewModel.
The above example is derived from this course : https://www.pluralsight.com/courses/wpf-mvvm-test-driven-development-viewmodels
I highly recommend it.

WPF/C# Link Two Variables together

I currently have a simple WPF application, in the MainWindow I will have a variable (In this case the variable is a class that holds data). Then I have a User Control which has the same variable.
Currently, I'm passing the variable with the ref keyword and it works perfectly fine, however, is this save/good practice? Is there a better way of linking this two variables together?
I am aware of the existence of DependencyProperty, however, I could not get it to work.
MainWindow:
public partial class MainWindow : Window
{
private TestClassWithInfo m_SelectedInfo;
public MainWindow()
{
InitializeComponent();
m_SelectedInfo = new DrawingInformation();
TestGridUC mp = new TestGridUC(ref m_SelectedInfo);
TestCanvas.Childrens.Add(mp);
}
}
TestGridUI:
public partial class TestGridUC : UserControl {
private TestClassWithInfo m_SelectedInfo;
public TestGridUC (ref TestClassWithInfo e)
{
InitializeComponent();
m_SelectedInfo = e;
}
}
TestClassWithInfo:
public class TestClassWithInfo
{
public Image imageTest;
public int intTest;
public TestClassWithInfo ()
{
m_img = null;
m_layer = 0;
}
}
I am aware of the existence of DependencyProperty, however, I could not get it to work.
A dependency property really is the way to go about it though:
public partial class TestGridUC : UserControl
{
public TestGridUC()
{
InitializeComponent();
}
public TestClassWithInfo Info
{
get { return (TestClassWithInfo)GetValue(InfoProperty); }
set { SetValue(InfoProperty, value); }
}
public static readonly DependencyProperty InfoProperty =
DependencyProperty.Register("Info", typeof(TestClassWithInfo), typeof(TestGridUC),
new PropertyMetadata(null /*or initialize to a default of new TestClassWithInfo()*/ ));
}
Now you can bind to that property from the xaml in your MainWindow:
<local:TestGridUC
Info="{Binding Info}"></local:TestGridUC>
If you need help with that part, as pr177 answered there are many tutorials on getting started with WPF with the MVVM pattern. The basics here would involve a view model object that contains a TestClassWithInfo public property that you bind to.
Have a look at the MVVM (Model-View-ViewModel) Pattern
There are many tutorials & introductions like that:
https://blogs.msdn.microsoft.com/ivo_manolov/2012/03/17/model-view-viewmodel-mvvm-applications-general-introduction/
or
https://social.technet.microsoft.com/wiki/contents/articles/32164.wpf-mvvm-step-by-step-2.aspx

Pass parameter to a constructor in the ViewModel

I am building a WPF browser application with MVVM pattern.
I have a first page (ConsultInvoice) with a dataGrid. When I double click on one of the row I want to navigate to another page (EditInvoice) passing the selected row in argument to my constructor.
I know if I want do things properly I should use a dependency injection, but I don't really see how to use it here.
How can I simply pass this constructor?
ConsultInvoiceViewModel
private Invoice _selected;
public Invoice Selected
{
get
{
return _selected;
}
set
{
_selected = value;
OnPropertyChanged("Selected");
}
}
private void Edit()
{
EditInvoiceViewModel editInvoice = new EditInvoiceViewModel(Selected);
/* doing something here*/
}
public ICommand EditCommand
{
get
{
return editCommand ?? (editCommand = new RelayCommand(p => this.Edit(), p => this.CanEdit()));
}
}
EditInvoiceViewModel
public class EditInvoiceViewModel : ViewModelBase
{
public Context ctx = new Context();
Invoice invoice;
PreInvoice preInvoice;
#region properties
private ObservableCollection<PreInvoice> collection;
public ObservableCollection<PreInvoice> Collection
{
get
{
return collection;
}
set
{
collection = value;
OnPropertyChanged("Collection");
}
}
#endregion
public EditInvoiceViewModel(Invoice inv)
{
/* do stuff*/
}
}
Basically you should avoid passing such parameters into the ViewModels constructor, as wiring it with Inversion of Control/Dependency Injection becomes a pain. While you can use Abstract Factory pattern to resolve objects with runtime parameters, it's imho not suitable for ViewModels.
Instead I always suggest using a form of navigation pattern, similar to how Microsoft's Patterns & Practices team has done with Prism. There you have an INavigationAware interface which your ViewModels can implement. It has 2 methods, NavigateTo and NavigateFrom.
And there is a navigation service. The navigation service will switch the views and before switching calling NavigateFrom in the current ViewModel (if it implements it. One can use it to check if data is saved and if necessary cancel the navigation. After the new View has been loaded and the ViewModel assigned to it, call NavigateTo in the newly navigated ViewModel.
Here you'd pass the parameters required for the ViewModel, in your case invoiceId. Try avoid passing whole models or complex objects. Use the invoiceid to fetch the invoice data and to populate your editing ViewModel.
A basinc implementation from my former answer (can be found here):
public interface INavigationService
{
// T is whatever your base ViewModel class is called
void NavigateTo<T>() where T ViewModel;
void NavigateToNewWindow<T>();
void NavigateToNewWindow<T>(object parameter);
void NavigateTo<T>(object parameter);
}
public class NavigationService : INavigationService
{
private IUnityContainer container;
public NavigationService(IUnityContainer container)
{
this.container = container;
}
public void NavigateToWindow<T>(object parameter) where T : IView
{
// configure your IoC container to resolve a View for a given ViewModel
// i.e. container.Register<IPlotView, PlotWindow>(); in your
// composition root
IView view = container.Resolve<T>();
Window window = view as Window;
if(window!=null)
window.Show();
INavigationAware nav = view as INavigationAware;
if(nav!= null)
nav.NavigatedTo(parameter);
}
}
// IPlotView is an empty interface, only used to be able to resolve
// the PlotWindow w/o needing to reference to it's concrete implementation as
// calling navigationService.NavigateToWindow<PlotWindow>(userId); would violate
// MVVM pattern, where navigationService.NavigateToWindow<IPlotWindow>(userId); doesn't. There are also other ways involving strings or naming
// convention, but this is out of scope for this answer. IView would
// just implement "object DataContext { get; set; }" property, which is already
// implemented Control objects
public class PlotWindow : Window, IView, IPlotView
{
}
public class PlotViewModel : ViewModel, INotifyPropertyChanged, INavigationAware
{
private int plotId;
public void NavigatedTo(object parameter) where T : IView
{
if(!parameter is int)
return; // Wrong parameter type passed
this.plotId = (int)parameter;
Task.Start( () => {
// load the data
PlotData = LoadPlot(plotId);
});
}
private Plot plotData;
public Plot PlotData {
get { return plotData; }
set
{
if(plotData != value)
{
plotData = value;
OnPropertyChanged("PlotData");
}
}
}
}
An example of the INavigationAware interface used in Prism can be found on the projects github repository.
This makes it easy to pass parameter and async load your data (where there isn't any clean way to do this via constructor, as you can't await an async operation inside the constructor without locking, and doing this kind of things in the constructor is very discouraged).

Using Ninject with MVVM Light

Using MVVM Light in a WPF MVVM application.
I want to use Ninject instead of SimpleIOC.
Even in a brand new WPF/MVVM Light v4 project, I get a null reference for MainViewModel when the Main Property in the ViewModelLocator is called by the XAML.
private static readonly StandardKernel kernel;
static ViewModelLocator()
{
if (ViewModelBase.IsInDesignModeStatic)
{
}
else
{
kernel = new StandardKernel(new mymodule());
}
}
public MainViewModel Main
{
get { return kernel.Get<MainViewModel>(); }
}
MyModule looks like this:
public class mymodule:NinjectModule
{
public override void Load()
{
Bind<MainViewModel>().ToSelf();
}
}
I've also tried
public class mymodule:NinjectModule
{
public override void Load()
{
Bind<MainViewModel>().To<MainViewModel();
}
}
Ninject kernel's .Get<T> does not return null.
Except in case you explicitly tell it to by doing:
Bind<T>().ToConstant(null);
Bind<T>().ToMethod(x => null);
Bind<T>().ToProvider<TProvider>() --> and TProvider.Create(...) returns null
It's very unlikely you have any of these.
So if there's a NullReferenceException when accessing the Main property, it must be because private static readonly StandardKernel kernel is null.
Now if the code you've provided us is a Minimal, Complete, and Verifiable example, that means ViewModelBase.IsInDesignModeStatic returns true.

How should Application.Run() be called for the main presenter of a MVP WinForms app?

I'm learning to apply MVP to a simple WinForms app (only one form) in C# and encountered an issue while creating the main presenter in static void Main(). Is it a good idea to expose a View from the Presenter in order to supply it as a parameter to Application.Run()?
Currently, I've implemented an approach which allows me to not expose the View as a property of Presenter:
static void Main()
{
IView view = new View();
Model model = new Model();
Presenter presenter = new Presenter(view, model);
presenter.Start();
Application.Run();
}
The Start and Stop methods in Presenter:
public void Start()
{
view.Start();
}
public void Stop()
{
view.Stop();
}
The Start and Stop methods in View (a Windows Form):
public void Start()
{
this.Show();
}
public void Stop()
{
// only way to close a message loop called
// via Application.Run(); without a Form parameter
Application.Exit();
}
The Application.Exit() call seems like an inelegant way to close the Form (and the application). The other alternative would be to expose the View as a public property of the Presenter in order to call Application.Run() with a Form parameter.
static void Main()
{
IView view = new View();
Model model = new Model();
Presenter presenter = new Presenter(view, model);
Application.Run(presenter.View);
}
The Start and Stop methods in Presenter remain the same. An additional property is added to return the View as a Form:
public void Start()
{
view.Start();
}
public void Stop()
{
view.Stop();
}
// New property to return view as a Form for Application.Run(Form form);
public System.Windows.Form View
{
get { return view as Form(); }
}
The Start and Stop methods in View (a Windows Form) would then be written as below:
public void Start()
{
this.Show();
}
public void Stop()
{
this.Close();
}
Could anyone suggest which is the better approach and why? Or there even better ways to resolve this issue?
What about the following:
// view
public void StartApplication() // implements IView.StartApplication
{
Application.Run((Form)this);
}
// presenter
public void StartApplication()
{
view.StartApplication();
}
// main
static void Main()
{
IView view = new View();
Model model = new Model();
Presenter presenter = new Presenter(view, model);
presenter.StartApplication();
}
That way, you don't need to expose the view to the outside. In addition, the view and the presenter know that this view has been started as a "main form", which might be a useful piece of information.
I would go for the second approach.
You could also get rid of the extra property by simply casting view to form in the void Main, since you know it is a form anyway at that point (I see no reason to make it more generic than that since it just starts the winform app)
Application.Run(view as Form);
Things get a bit more complex if you allow more than one way to exit the application (e.g.: a menu item for exiting), or if you prevent closing of the application under certain conditions. In either case, the actual invocation of application closing should usually be invoked from presenter code rather than by simply closing the concrete view. This can be accomplished by using either the Application.Run() or Application.Run(ApplicationContext) overloads and exposing the application exit action via inversion of control.
The exact approach to registering and using the application exit action would depend on the IoC mechanism (e.g.: service locator and/or dependency injection) that you are using. Since you haven't mentioned what your current IoC approach might be, here's a sample that's independent of any particular IoC frameworks:
internal static class Program
{
[STAThread]
private static void Main()
{
ApplicationActions.ExitApplication = Application.Exit;
MainPresenter mainPresenter = new MainPresenter(new MainView(), new Model());
mainPresenter.Start();
Application.Run();
}
}
public static class ApplicationActions
{
public static Action ExitApplication { get; internal set; }
}
public class MainPresenter : Presenter
{
//...
public override void Stop()
{
base.Stop();
ApplicationActions.ExitApplication();
}
}
This basic approach could be adapted quite easily to your preferred IoC approach. For example, if you're using a service locator, you would probably want to consider removing at least the setter on the ApplicationActions.ExitApplication property, and storing the delegate in the service locator instead. If the ExitApplication getter were to remain, it would provide a simple façade to the service locator instance retriever. e.g.:
public static Action ExitApplication
{
get
{
return ServiceLocator.GetInstance<Action>("ExitApplication");
}
}
You could do it in a hundred ways to achieve the ultimate goal of separability of concerns. There is no hard and fast rule here, the basic idea is that presenter deals with presentation logic of the view, while the view has only the dumb knowledge of its own GUI specific classes and stuffs. Some ways I can think of (to broadly put):
1) View kick-starts things and let it decide its presenter. You start like, new View().Start();
// your reusable MVP framework project
public interface IPresenter<V>
{
V View { get; set; }
}
public interface IView<P>
{
P Presenter { get; }
}
public static class PresenterFactory
{
public static P Presenter<P>(this IView<P> view) where P : new()
{
var p = new P();
(p as dynamic).View = view;
return p;
}
}
// your presentation project
public interface IEmployeeView : IView<EmployeePresenter>
{
void OnSave(); // some view method
}
public class EmployeePresenter : IPresenter<IEmployeeView>
{
public IEmployeeView View { get; set; } // enforced
public void Save()
{
var employee = new EmployeeModel
{
Name = View.Bla // some UI element property on IEmployeeView interface
};
employee.Save();
}
}
// your view project
class EmployeeView : IEmployeeView
{
public EmployeePresenter Presenter { get; } // enforced
public EmployeeView()
{
Presenter = this.Presenter(); // type inference magic
}
public void OnSave()
{
Presenter.Save();
}
}
A variant of the above approach would be to enforce stronger generic constraint on view and presenter, but I dont think the complexity outweighs the benefits. Something like this:
// your reusable MVP framework project
public interface IPresenter<P, V> where P : IPresenter<P, V> where V : IView<P, V>
{
V View { get; set; }
}
public interface IView<P, V> where P : IPresenter<P, V> where V : IView<P, V>
{
P Presenter { get; }
}
public static class PresenterFactory
{
public static P Presenter<P, V>(this IView<P, V> view)
where P : IPresenter<P, V>, new() where V : IView<P, V>
{
return new P { View = (V)view };
}
}
// your presentation project
public interface IEmployeeView : IView<EmployeePresenter, IEmployeeView>
{
//...
}
public class EmployeePresenter : IPresenter<EmployeePresenter, IEmployeeView>
{
//...
}
Disadvantages
interacting between forms are less intuitive to me.
Steps involved:
implement IEmployeeView
instantiate presenter by calling PresenterFactory and passing this from the view constructor
ensure view events are wired to their corresponding presenter methods
start off, like new EmployeeView()....
2) Presenter kick-starts things and let it decide its view. You start like, new Presenter().Start();
In this approach presenter instantiates its own view (like approach 1) by means of some dependenchy injection or so, or view can be passed to presenter's constructor. E.g.
// your reusable MVP framework project
public abstract class IPresenter<V> // OK may be a better name here
{
protected V View { get; }
protected IPresenter()
{
View = ...; // dependenchy injection or some basic reflection, or pass in view to ctor
(View as dynamic).Presenter = this;
}
}
public interface IView<P>
{
P Presenter { get; set; }
}
// your presentation project
public interface IEmployeeView : IView<EmployeePresenter>
{
void OnSave(); // some view method
}
public class EmployeePresenter : IPresenter<IEmployeeView>
{
public void Save()
{
var employee = new EmployeeModel
{
Name = View.Bla // some UI element property on IEmployeedView interface
};
employee.Save();
}
}
// your view project
class EmployeeView : IEmployeeView
{
public EmployeePresenter Presenter { get; set; } // enforced
public void OnSave()
{
Presenter.Save();
}
}
Steps involved:
implement IEmployeeView
ensure view events are wired to their corresponding presenter methods
start off, like new EmployeePresenter(....
3) Event based, observer style
Here you could either encapsulate presenter in view (instantiate presenter in view) like approach 1 or encapsulate view in presenter (instantiate view in presenter) like approach 2 but in my experience latter will always be the cleaner design to work with. An e.g. of latter:
// your reusable MVP framework project
public abstract class IPresenter<V> where V : IView
{
protected V View { get; }
protected IPresenter()
{
View = ...; // dependenchy injection or some basic reflection, or pass in view to ctor
WireEvents();
}
protected abstract void WireEvents();
}
// your presentation project
public interface IEmployeeView : IView
{
// events helps in observing
event Action OnSave; // for e.g.
}
public class EmployeePresenter : IPresenter<IEmployeeView>
{
protected override void WireEvents()
{
View.OnSave += OnSave;
}
void OnSave()
{
var employee = new EmployeeModel
{
Name = View.Bla // some UI element property on IEmployeedView interface
};
employee.Save();
}
}
// your view project
class EmployeeView : IEmployeeView
{
public event Action OnSave;
void OnClicked(object sender, EventArgs e) // some event handler
{
OnSave();
}
}
// you kick off like new EmployeePresenter()....
Disadvantage:
You have to wire events on both view and presenter sides - double the work
Steps involved:
implement IEmployeeView
ensure iview events are called from view event handler methods
ensure iview event members are initialized from presenter
start off, like new EmployeePresenter()....
Limitations of language sometimes make design patterns more difficult. For e.g, had multiple inheritance been possible in C#, it was only a matter of having an abstract base view class with all the implementation details except UI specific components which could be then implemented by view class. No presenters, classic polymorphism and dead simple! Unfortunately this is not possible since most view classes in .NET (like Form of WinForms) already inherits from a super view class. So we have to implement an interface and go for composition. Also, C# doesnt let you have non-public members in an interface implementation, so we are forced to make all members specified in IEmployeeView public which breaks the natural encapsulation rules of the view class (i.e. other views in the view project can see details of EmployeeView irrelevant to them). Anyway, using power of C#'s extension methods a much simpler but very limited approach can be taken.
4) Extension method approach
This is just silly.
// your presentation project
public interface IEmployeeView
{
void OnSave(); // some view method
}
public static class EmployeePresenter // OK may need a better name
{
public void Save(this IEmployeeView view)
{
var employee = new EmployeeModel
{
Name = view.Bla // some UI element property on IEmployeedView interface
};
employee.Save();
}
}
// your view project
class EmployeeView : IEmployeeView
{
public void OnSave()
{
this.Save(); // that's it. power of extensions.
}
}
Disadvantages:
fairly unusable for anything remotely complex
Steps involved:
implement IEmployeeView
ensure this.... extension method is called from view events
kick off things by calling new View...
Of all 2 and 3 look better to me.

Categories

Resources