Use same viewmodel different windows - c#

My project is build on MVVM. Currently I have a list where i can select an object and add them to another list. What I want to make is a new window where this list is shown (the list with objects that are added) and edit that list in the new window (delte an item from that list).
How should I pass the data (selected object) to another window and be able to update them there?
I currently have it working in one view. In some related questions they advice MVVM light so I tried looking for that, from what I red mvvm light is mostly used to replace the notify property change. Should I use mvvm light or are there some specific patterns I could use?
Both windows will be open at the same time.

If you want to share your ViewModel between windows, you can use a ViewModelLocator. It is not specific to MvvmLight, it just creates one for you with its project template. You can implement it yourself, it is basically a container for your ViewModels. You can look here for the implementation details.

I've got to say that I'm not sure that these are the best approaches and if they are common, it's just what me and my colleagues were using in a WinRT application, so I'll be really glad if someone comes up with something better (both of these are not that clean).
I can think of two ways to pass data (without persisting it)
Pass parameters on page navigation
Have common shared class (Static or singleton class with some common data accessible from all ViewModels)
For passing on navigation:
I have this method in my Navigation service class:
public virtual void NavigateTo(Type sourcePageType, object parameter)
{
((Frame)Window.Current.Content).Navigate(sourcePageType, parameter);
}
and I use it like this in navigation commands:
Navigation.NavigateTo(typeof(PageType), someParameters);
Then you could get the values in the code behind of the navigated page
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var receivedParameter = e.Parameter as TheTypeOfThePassedParameter;
}
And from there to pass them to the ViewModel, maybe there is an option to pass this without code in the code behind but I've not tried this.
Having shared class:
This is pretty much straightforward just have static class or a singleton with the desired fields.

Related

MVVM Handling Window Management using Factory Approach

I delegate creation(showing) of my Windows to my WindowFactory, that attaches a ViewModel to the View and shows the window. It is injected into my MainViewModel Constructor parameters.
The factory itself is very simple:
public class ProductionWindowFactory : IWindowFactory
{
public void CreateNewWindow()
{
PhoneWindow window = new PhoneWindow();
{
window.DataContext = new phoneWindowViewModel();
}
window.Show();
}
}
Now, I'm aiming at implementing more functionality of my new windows, that will happen on certain button clicks IN that new window.
As I am fairly new to Factories in general, I'm struggling to grasp a certain concept:
Example:
We have a ViewA that has a ViewModelA attached to it.
That view has a button with a command attached, that tells our WindowFactory to show a new ViewB.
ViewB has a ViewModelB and a close button, that tells it to close ViewB.
Now, since we shouldn't reference our ViewB in our ViewModelB, we have to somehow let it know which view it should close.
I have come up with possible ideas / solutions, but I would really
appreciate you letting me know which one follows the MVVM and Factory
pattern "the most", and which one is usually used in such situations.
Make our ViewModelB take an instance of windowFactory that created ViewB as a parameter on initialization, and build a method in the Factory that closes ViewB and is executed through button click -> command.
Create an IWindowManager? that inherits from IWindowFactory and build a WindowManager class, that extends the capabilities of our WindowFactory, and push it in ViewModel constructors as described above.
Any other correct solution, that I am completely unaware of?
Please bear in mind, that the above is just an example. Ideally, I'd like to implement more of advanced functionality to my windows, and have an ability to create & manage multiple different ones using that one factory.
I have not attached much code, since I'm still at the stage of learning and deciding which solution should I go with.
EDIT - REGARDING POSSIBLE DUPLICATE:
My question differs from the proposed duplicate, as the other one is simply about managing of closing windows - My question is about doing that as well, but following a FactoryPattern.
I have specified very clear guidelines in what I am trying to achieve and in what ways, that are completely different from the question linked.
First of all, the answer is none. The job of a factory is to create new objects, think of it as an elaborate new operator. Also, the idea of following a pattern "the most" is problematic in and of itself. You employ patterns because they help you achieve certain goals, e.g. you employ mvvm to evade coded-ui tests as much as possible, because they are fragile, normally.
That being said, what to do with its view is completely up to the view's view model.
Example: if one view model needs to close its own window, do it with a command as illustrated in the comment. If a view has a close all-button, its view model will have a dependency on some kind of window registry that can enumerate all open windows for the close all-command to close.
When looking at your view model, try to come up with an idea of what services it needs from the rest of the application, and inject those dependencies as interfaces. When implementing the interfaces, most likely there will be classes that implement more than one, e.g. WindowManager might implement IWindowFactory and IWindowRegistry thus making it very easy to put all newly created windows into the list of open windows. The window will have a dependency on the IWindowRegistry, too, most likely, to unregister itself when it gets closed.
The duplicate was not far off. Here is a simple adaptation of the scenario in OP
interface IView {
void Close();
}
class ViewAdapter : IView {
readonly Window view;
public ViewAdapter(Window view){
this.view = view;
}
public void Close() {
view.Close();
}
}
public class ProductionWindowFactory : IWindowFactory {
public void CreateNewWindow() {
var view = new PhoneWindow();
var viewAdapter = new ViewAdapter(view)
var viewModel = new phoneWindowViewModel(viewAdapter);
//Bind
view.DataContext = viewModel;
view.Show();
}
}
If the view model wants to instruct that the view be closed it can ask the injected contract to do so.

Best approach for calling a web service (or similar) with MvvmCross

I've been giving this some thought lately and I was hoping someone who has better knowledge of MvvmCross than myself can shed some light on this. Given the nuances between each mobile platform there are probably a few different factors that can affect this problem. But for this scenario let's assume we want the best approach for a cross platform solution.
So let's say we have a basic View and a ViewModel class setup. Here's an iOS example.
View
public partial class FirstView : MvxViewController<FirstViewModel>
{
public FirstView(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
Request = new MvxViewModelInstanceRequest(FirstViewModel.NewInstance());
base.ViewDidLoad();
}
}
View Model
public class FirstViewModel : MvxViewModel
{
public static FirstViewModel NewInstance()
{
return Mvx.IocConstruct<FirstViewModel>();
}
public FirstViewModel()
{
}
}
Now at the loading of this View or at some point just before the view is created we want to fetch some data from the web using a service that we inject using dependency injection; because the displaying of the view depends on that data. Here lies the problem.. at which point from a platform perspective and in the MvvmCross lifecycle would be the most appropriate place to call the web fetch function in the service.
With regards to platform I would assume that we should do it once the view loads. Because if the fetched data is anything other than simple data types it will be inconvenient to work with on Android, as one would have to persist the data to disk and retrieve it after the navigation, due to serialization between activities.
So assuming we called the web fetch during the view loading process. Where is the best place in the MvvmCross architecture to fire it off, that most closely follows the design paradigms. e.g. The View Model. Is there any lifecycle methods that someone could recommend to call it inside as well. Something like the Start method, called after the view model has been created.
First of all, I don't understand why you won't let the platform itself instantiate and do it's ViewModel lifecycle instead of creating a new instance of the ViewModel using Mvx.IocConstruct. That method does not invoke the ViewModel lifecycle and will not call neither Init or Start on the ViewModel.
If you let the platform do this for you, first the Init method will be called with the arguments that you set when using ShowViewModel<T>(args).
When ViewDidLoad invokes the Start method will subsequently be called.
This gives you two places to invoke the Service that you inject in the ctor of the ViewModel.
If you want more control over when to download the data, you could create some ICommand's, which you invoke on your ViewModel in any of the ViewController lifecycle methods. This could be in the ViewWillDisappear/ViewDidDisappear method, or you could fetch the data.
There are so many ways you can do this. In the end it is entirely up to you, and you can't possibly know when a user decides to change to another View. However, you can make qualified guesses and try fetch data before the user actually wants it.
There is a nice article for you to read here, by Rob Gibbens on how you could do Resilient network services. It describes how you could speculatively fetch resources based on what the user is doing, and this way have something ready for the user to see when he enters the View. This could be cached data or fresh data that you are fetching after showing the cached version.
In any case, I would suggest you stop loading your ViewModel's with Mvx.IocConstruct and let MvvmCross handle this for you in order to get lifecycle methods invoked.

Architectural question regarding Interfaces implementation and extensibility

I've created a sample app, just to test and try out some of wpf's capabilities. I was basically trying out the databinding in wpf, and did the rest of stuff more or less quickly. THen, i faced an arquitectural problem (yes, should have thought in advance before starting coding :) ) and i wanted to know what's the best refactoring solution for it.
I have a simple interface that returns a list of objects, based on a defined process.
public interface IDoStuff<out T>
{
IEnumerable<T> Do(string someParam);
}
i've created a couple of implementations for this interface. Then i have a view in wpf, which has a dropdown with hardcoded values, and depending on what you select, instatiates the implementation of the interface and populates some list
foreach (var item in new IDoSTuffImplementation1()<MyObj>.Do("imp 1"))
{
MyObjs.Add(item);
}
ater on MyObjs is the DataContext for a listview, and displays things and so on and so forth, but it's out of the main question.
this is all hardcoded and not very nice. If i was ever to implement a new interface, i'd need to add it to the dropdown, and create a new foreach for that specific implementation (more duplicated code)
Ok, here's my impression on making this better/refactoring for extensibility.
I was thinking a good approach would be to use some kind of MVVM pattern, making the wpf view into a view + viewmodel. the viewmodel would use some kind of IoC like spring, which would (by xml) instantiate one specific implementation of the interface, and inject it to the viewmodel, which would then call its "Do" method and everyone happy. So this way, the only thing that would be needed to do when we implement a new component, is to add it to the xml config file.
Suggestions, Comments? what's the best approach, if any?
thanks!!
Actually I don't see any architecture changes if you provide another implementation of the interface. You already have a good architecture when using MVVM, so the task you are trying to accomplish will not change the architecture, but will extend your application using the architecture.
I suggest you change you Method to a Property instead. And assign that property to ComboBox's ItemsSource property to ease up your coding using data binding.

Design Question

I have a control in which we show some links to different sites based on some business rules. Currently all business logic to build link list is in control.
I plan to move out the busincess logic from the control.
what will be a good design for this?
can I use any design pattern?
You shouldn't get too caught up in thinking about patterns. Most of the time they are overkill and add too much complexity. Particularly with a trivial scenario like this.
Just utilize good object-oriented practices and you'll be fine. Encapsulate your business logic in another class and provide public properties for your control to access it. Keep it simple!
How about the Model-View-Presenter pattern?
Another good choice might be the Mediator pattern.
Do you really need a custom control for this?
Model-View-Controller suggests that you only have display logic in a control.
Find a solution that allows you to make small changes to a built in control (ListView) and create a custom data set somewhere else to pass to it.
I not sure how you implement your business rules but here is an idea...
I would databind your web forms list control.
public class YourLinks
{
// You could do it by overloading the constructor...
// Again not sure how you determine what links should be displayed...
// If you had consistent types you could make your constructor internal
// and then create a YourLinkBuilder see below...
public YourLinks(User user, Region region)
{
}
public YourLinks(City city)
{
}
// Databind to this method...
public IEnumerable<string> GetLinks()
{
// return your links...
}
}
public class YourLinkBuilder
{
public static YourLinks BuildPowerUserLinks()
{
return new YourLinks(new PowerUser(), new Region("Washington"));
}
public static YourLinks BuildVisitorLinks()
{
return new YourLinks(new VisitorUser(), new Region("Empty"));
}
}
Given the little information provided, I would suggest you create a model of just the links (and its related data). So that you can pass the LinksModel to your views for rendering. Or pass your LinksModel to your existing model (as a sub-model).
Either way, all this data is encapsulated. So if you want to add data to it later, it will not change your method signatures (or general contract). If you want to remove data from it, same advantage. If you want to remove it entirely, its only one object and simplifies the removal.
You can also build links view renderers so that it and only it knows how to visually display the LinksModel. So within your view, you can delegate the visual aspects of the links info to such renderers instead of having logic within your existing view. If you want to change how links view looks later or want to give the user the power of selecting different renditions, you can simply use different renderers rather than jamming your entire code with 'if' blocks.
Jeach!
You should use Model-View-Presenter for sure. In the view, you should have your control.
The control's responsibility should be merely to take input from the user, validate it, and pass that information to the presenter. The presenter should then interact with the model, where your business rules are stored.
From the model, you may wish to return the links that are then passed to the control for display, or you may wish to return some metadata that is passed to another system to retrieve the links.
What I would do is use the Strategy pattern in the model, so that you can easily swap in and out different versions of your business rules.
To abstract interaction with your backend datasource (if you have one) have a look at Martin Fowler's Gateway pattern.

WPF Data Binding to external data model

I've recently started develping an application using WPF and I'cant really wrap my mind around following thing:
I have a Domain Model of my application which is simple POCO objects serialized to/from harddisk. Then I have the WPF application and I'd like to bind it to various parts of the model. I need to be able to notify UI of changes to underlying model (eg. implement INotifyPropertyChanged) BUT I want to do that without interfeering with my model (read without modifying current implementation of the model). How can I implement changes notification other than modifying the model?
Reason why I want to do that is that I share the model among multiple projects, only one being WPF, and I don't want to add unncecessary code to the model.
One thing that came to my mind was to create "copy" of the model (with INotifyPropertyChanges and BindingLists etc.) but that seems to be hard to maintainn...
Thanks in advance.
Ondrej
Check this out MVVM
Download its source code see the hierarchy.
Basically you still keep simple POCO objects as your models. Then you create a ViewModel around the model like this:
public class CustomerViewModel : INotifyPropertyChanged
{
readonly Customer _customer;
public CustomerViewModel(Customer customer)
{
_customer = customer;
}
public string FirstName
{
get { return _customer.FirstName; }
set
{
if (value == _customer.FirstName)
return;
_customer.FirstName = value;
OnPropertyChanged("FirstName");
}
}
...
}
I see two possible solutions here:
Use a separate model for WPF screens only (MVVM pattern). This will require maintaining two different models, also be prepare for lots of mapping code.
Use PostSharp to "enhance" your model with all necessary boilerplate code. Here you can find example of automatic INotifyPropertyChanged implementation. Remember that introducing PostSharp to the project is an important decision, so I suggest getting familiar with it first.

Categories

Resources