How to pass ViewModel to CodeActivity using WF4 with MVVM and WPF - c#

I am trying to integrate my current WPF/MVVM application to Workflow Foundation 4.0.
Currently one of my ViewModel methods is invoking my sample CodeActivity sending it some parameters.
Inside of my CodeActivity execute method I need to call some methods from the calling ViewModel. I would like to know what the best approach is to do this. So far I have identified three possible ways:
Send my ViewModel instance as an input argument to my CodeActivity
Send my ViewModel instance through a Constructor in my CodeActivity like public MyCodeActivity(ViewModel vm)
Wrap my CodeActivity in a WorkflowApplication and send my ViewModel instance as an extension using SynchronizationContext
So far I have tested options 2 and 3 and they work well apparently.
What is the optimal way to do this to avoid any issues like thread synchronization problems or other?
Thanks in advance,
Edit:
Just to mention a possible scenario: If user picks value 'X' from a given dropdown list in my View I need to add object childA and childB to an ObservableCollection contained by a ParentObject exposed through a public property in my ViewModel. The logic to create the child objects and add them to the parent are in my ViewModel. But I want Workflow to contain the Business Rule itself.

Why does your CodeActivity need to know anything about a specific view model? I would look for another solution that allows your activity to maintain as much independence as possible. Two options I can think of off the top of my head:
Use an abstract class or interface so that your activity is not bound to a single viewmodel, i.e., InArgument<IViewModel>
Facilitate communication using an event aggregation pattern (if possible if WF4, not too sure on this yet?), i.e., give the activity what it needs to do it's job and let your view model listen for an event to receive updates from the activity
Without knowing the specifics of your application, I don't know which option would work best (or work at all), but I would avoid a direct connection between a given view model and a given CodeActivity.

Related

MvvmLight Messaging - What is the proper way to register and unregister a message?

I ran into the issue where a Message will fire multiple times, because a Message is being registered multiple times when it is registered in the constructor of a View. A large majority of the S.O. posts, websites, blogs show an example like this:
public ConstructorOfView() {
DataContext = viewModelObject;
Messenger.Default.Register<SomeClass>(recipient, token, method);
}
public someUnloadOrNavigateFromMethod() {
Messenger.Default.Unregister<SomeClass>(parameters and more);
}
Unregistering seems to have no effect for me. Some examples say to register messages inside the ViewModel. This doesn't make sense to me for two reasons: 1) If you set the DataContext of a page to a ViewModel, the ViewModel constructor gets called twice again just like the view constructor. 2) If you register a message inside the ViewModel, how exactly do you tell the view to fire a method, other than making it public static, that shows a message dialog?. The third option of just calling a UI-related element like a dialog inside the viewmodel seems to violate the concept of MvvM.
What is the proper way to register and unregister messages?
Some posts have recommended having the viewmodel call Cleanup(), but somehow you need to register messages to the viewmodel, but it's not clear to me how if you set the recipient of the message as the viewmodel, how does the viewmodel call a non-public-static method in the view to change/display UI?
I normally use a pattern where my view models are registered in an IOC container (take a look at the VireModelLocator class in the MVVMLight starter application) and register messages in the ViewModel constructor.
That way, since the ViewModel creation is handled by IOC, you'll have no issues with multiple creations of the relevant view, the message registration happens only once.
Keep also in mind that registering and unsegistering messages will easily take you to a world of very difficult to find bugs where you send a message but for some reason there's no handler registered jet.
I would also add that 99% of view/viewmodel interaction should happen throgh binding.
I strongly suggest to review the WPF application template that MvvmLight provides in order to identify and understand programming patterns.

Startup Sequence for C# WPF MVVM Applications

I'm currently going back to designing some GUI Applications using WPF + MVVM, I now find it much easier to understand than when I first encountered it.
One question that troubles me however is the startup of the application. From my view, there are two approaches:
Start from the Main Window View, have its ViewModel be instantiated by some means which again instantiates the Model it represents. This puts the View / GUI in the "operating" position.
The other way would be to override the OnStartup routine in the Application class (John Smith does it this way in his The MVVM-Design Pattern MSDN Article) and start by creating the model, passing it to the ViewModel Contructor and assign the newly created ViewModel to the DataContext of a separately created View / Window.
Is either way fine (in this case, what may be reasons to prefer one over the other) or is one violating MVVM rules?
Your first approach is correct:
Start from the Main Window View, have its ViewModel be instantiated by
some means which again instantiates the Model it represents. This puts
the View / GUI in the "operating" position.
The viewmodel then becomes the DC for the View. There should be a 1:1 of View to ViewModel.
You want each class to be able to be instantiated with as few dependencies as possible.
My ViewModel ctors really only consist of an argument for passing a class containing View-Specific callbacks, based on an interface.
Model m = null;
IViewCallbacks cb;
public MainViewModel(IViewCallbacks mainViewCallbacks)
{
this.cb = mainViewCallbacks;
m = new Model();
}
The ViewModel instance has instances of the model(s) that I need to be able to access. The vm backing the view should be the in charge of instantiating these, otherwise your unit testing is going to suffer because of external dependencies (that instance of the model that you need to pass in via the ctor).

Advice on setting up model in a MVVM application using caliburn

I'm new to MVVM so I'm trying to figure out what is the best way to do this. I'm using WPF with Caliburn Micro for this.
I have two different views (each with their view models) for the model I'm trying to manipulate. One view shows the model in a tree view while the other shows a table view of the data.
My model basically looks something like the following
public class Foo
{
public string Name {get;set;}
public string[] Categories {get;set;}
}
The Views are different ways to visualize collections of Foo. The table view is pretty straightforward, but the tree-view will group Foo by the category it contains.
So if an instance of Foo is something like
var fo = new Foo(){Name="one",Categories=new[]{"a","b","c"}};
Then the treeview would be
a
|_ one
b
|_ one
c
|_ one
I have two questions about how to connect the model to the view model in the spirit of MVVM.
What is the best way to populate the viewmodels from the model for the different views? I was thinking something like a singleton FooManager that is accessed from the view models. Or would using the caliburns SimpleContainer be better suited for this?
Lets say I manipulate Foo in the table view by changing it's category collection. How would I propagate the change to the treeview, since that would mean that Foo would appear in a different tree node? Would Foo need to implement PropertyChangedBase' and somehow bubble up the changes to the other ViewModel? Or would it be better forFooManagerto implementPropertyChangedBase`. Seems like the latter would be more reasonable.
TIA
For collections that change reference BindableCollection and are presented on the view.
As for bringing data into a view you can do it through a combination of DI/IoC, via constructor injections on the ViewModel in question. Most of that is done thru Interfaces that can be found in the Container of your choosing either SimpleContainer to MEF if you prefer or what ever IOC/DI container you choose really, the framework is such that can be extended with any container. Going with Interfaces allows for mocking and unit testing of the viewmodels.
Yes bubbling of the change to the View is usually done through what you had though by means of implementing INotifyPropertyChange which is part of the PropertyChangedBase class object.
One thing that will probably rear its ugly head is that Collections based off ObservableCollection don't necessarily bubble the changes of the underlying item's properties in the collection, that is an entirely different thread on SO

Prism How to bind Module View to app wide property

I know this may seem silly but, what is the best way to bind to Application Wide properties using MVVM and Prism?
Problem: ConnectionStatus Status {...} (Implements INotifyPropertyChanged etc..)
How do I go about accessing this property in specific modules? I want to be able to use the Status property across different modules?
What is the best way of getting this data across different modules?
Solutions
Currently I am leaning towards having the following view model in the infrastructure project (shared across modules)
namespace Project.Infrastructure
{
public class AppViewModel
{
public ConnectionStatus Status {...}
}
}
And in IoC define AppViewModel as Singleton, and pass this in the constructor of ModuleViewModel
namespace Project.ModuleA
{
AppViewModel _appViewModel;
public class ModuleViewModel
{
public ModuleViewModele(AppViewModel appViewModel)
{
....
}
}
}
Question
Is this the best way to do this or is there a better way of doing this?
E.g.
Using EventAggregator and ConnectionStatusChangeEvent to subscribe and publish to changes in the connection? But in this case if someone subscribes to the event after it got pubblished (such as online) they will not get any starting value, so a IStatusService could be used at the start?
Using RegionContext and binding that to the Status property in the Shell? But this seems to defeat the purpose of Shell not knowing what the Modules use etc..
Or is there something that I have completely missed?
I have read the whole Prism(v4) documentation and just not 100% sure of which is the best way of implementing this.
I do not like ViewModels knowing about each other. I took the approach you listed in E.g #1 - that EventAggregator assists in moving information around for me. I do this currently with a database connection and settings, both used throughout viewmodels. I pass the model property around after it is created first time and when updated.
The ViewModel that creates the model subscribes to a Request and UpdateRequest, and publishes a Response. So a Request returns the current property, UpdateRequest will refresh or recreate as appropriate.
The Response is pushing to any listeners - such as a newly created ViewModel who has in its constructor a publish of the Request. This means that the constructor doesn't initialize everything, your going to have the Response listeners covering extra work, and sometimes you may need to wait for multiple responses to fully initialize.
You asked what is the best way... - I feel my answer is right, but do what is right for your project. I like strict MVVM, but it doesn't always have to be so rigid.

Model view presenter, how to pass entities between view?

Edit : Accepted Chris Holmes response, but always ready to refactor if someone come up with a better way! Thanks!
Doing some winforms with MVP what is the best way to pass an entity to another view.
Let say I have a CustomerSearchView/Presenter, on doubleClick I want to show the CustomerEditView/Presenter. I don't want my view to know about the model, so I can't create a ctor that take an ICustomer in parameters.
my reflex would be,
CustomerSearchView create a new CustomerEditView, which create it's own presenter.
Then my CustomerSearchView would do something like :
var customerEditView = new CustomerEditView();
customerEditView.Presenter.Customer = this.Presenter.SelectedCustomer;
Other possible approach would be a CustomerDTO class, and make a CustomerEditView that accept one of those CustomerDTO, but I think it's a lot of work something simple.
Sorry for basic question but all example I can find never reach that point, and it's a brownfield project, and the approach used so far is giving me headache...
I don't know exactly how you are showing your views, so it's a bit difficult to give you specific advice here. This is how I've done this sort of thing before:
What we did was have the CustomerSearchViewPresenter fire an event like OpenCustomer(customerId). (That is assuming that your search view only has a few pieces of Customer data and the customerId would be one of them. If your search view has entire Customer objects listed then you could call OpenCustomer(customer). But I wouldn't build a search view and allow it to populate with entire objects... We keep our search views lightweight in terms of data.)
Somewhere else in the application is an event handler that listens for the OpenCustomer() event and performs the task of creating a new CustomerEditView w/ Presenter (and I'm going to defer to my IoC container do this stuff for me, so I don't have to use the "new" keyword anywhere). Once the view is created we can pass along the id (or customer object) to the new CustomerEditView and then show it.
This class that is responsible for listing the OpenCustomer() event and performs the creation of the CustomerEditView is typically some sort of Controller class in our app.
To further simplify this situation, I've done this another way: I create both the CustomerSearchView (& presenter) and CustomerEditView (& presenter) when the application or module starts up. When the CustomerSearchView needs to open a Customer for editing, the CustomerEditView becomes the responder to the OpenCustomer event and loads the data into itself, and knows how to show itself in whatever container it is supposed to do.
So there's multiple ways to do this.
How about:
//In CustomerSearchPresenter
var presenter = new CustomerEditPresenter();
var customerEditView = new CustomerEditView(presenter);
presenter.SetCustomer(customer);
//In CustomerEditPresenter
public void SetCustomer(customer)
{
View.Name = customer.Name;
View.Id = customer.Id;
...
}
In think your customer search view should just delegate to its presenter you need to have an action execute.
There are a couple of crucial insights to get a natural flow in any MVP code:
It's the presenter that drives the view, not the other way around.
Because of 1. the view need not know about the presenter's existence. Less dependencies usually means easier maintenance.
In C#, I find events being a great asset when decoupling presenters from views. More details in a previous answer: Model-View-Presenter in WinForms
I would look at MS Prism 4, and their nice Navigation interface. Also look at Silverlight and WCF Navigation. They are well done and handle things like prompting the user for confirmation from "dirty" forms, with cancellation.
I would look at the PageFunction() documentation in WCF as well, for how to "call" a page from another, and get back info.
Here's how it works (javascript, sorry):
User double-clicks customer on customer list:
CustomerList.onDblClick(customerId){
app.fireEvent('customerEditRequest', id)
}
...
app.onCustomerEditRequest(id){
this.mainRegion.requestNavigate('customers/edit', id);
}
If navigation to edit view was successful...
CustomerEditView.onNavigatedTo(context){
this.model.load(context.parameters.id));
}
CustomerEditView.onSaveButtonClick(){
this.model.save();
app.fireEvent('customerEdited', id);
}
...
app.onCustomerEdited(id){
app.mainRegion.requestNavigate('customerlist', id);
}
There are a few different ways you could do it:
send a callback function to the edit form, from the customer list. edit form will call it, and you do what you want when it's called.
have the edit form raise on "customerEdited" event that you listen to and react to (no app-wide bus)
use an application-wide Event Bus to manage the events centrally, shown.
I used to have my views communicate with their presenters, but have moved away from that. It doesn't conform to the original definition of a pattern (not a reason in itself for deviating just a contributing factor to exact those benefits). Views ideally should be kept as dumb and with as few dependencies as possible. View should communicate w/ Presenter (any "observers") via delegates/events/some "fire-and-forget" mechanism. As a matter of fact, I've introduced a controller into MVP specifically to intercept View events and either re-fire to presenter (rarely) to communite w/ Presenter, or to communicate with a system or Presenter-specific event bus - enabling me to change user action alerting mechanisms w/out touching the view. Have to be careful with an event bus though; pretty soon you start throwing all events in there, app gets chatty/bogged down in handling events, and events aren't the fastest things in .Net. Sunchronization is an added concern, esp if ur app need to have a more "conversational" interaction with your user.
Should bear in mind that although Presenter is usu view/process-specific, views (and view-models) can be reused; having the View in a containment/delegation relationship with the Presenter strongly couples View/limits its reuse. This could be reduced by some DI, but I find DI containers to be unnecessary complexity in most cases (since I have to know how to create objects anyway and how often do you change out an object for another semantically similar one after creating/testing it?). Concrete dependency goes nowhere except another layer/adds more obscurity/makes things more difficult to debug/trace. Been on a "simplicity" kick lately though, and mostly prefer to do my on Factory/object creations/ORM mappings for most apps, since there's usu a "1-to-1" btw db tables/entities and n need for the added complexity of a generic 3rd-party ORM tool that by taht generic context/needing to serve different apps has to make things harder than they need to be, even if u understand how they work (not the point).
Moreover, it's still quite feasible for View to observe Model in MVP (as in MVC), so I wouldn't be so quick to rule this out. I don't prefer to do this myself, but it' doesn't "break" the pattern. Matter of fact, I developed something similar to MVP about a decade ago because I didnt like the "circular loop" btw the MVC components (View knowing about Model); I preferred to have the cleaner separation btw View and Model that all these patterns (including MVC) professed, as well as a desire to keep View as dumb as possible (observing Model woujld mean View would need more intelligence to process Model changes). What I ended up doing was something like MVVM and strategy patter, where I used "substructures" of the model to pass in to the View, serving as "change notifiers". This kept everything view purpose-specific and flexible/reusable (tough combo).

Categories