How to pass a View to my ViewModel so an I*Service can use that View to do something - mvvm

https://github.com/brianchance/MvvmCross-UserInteraction is a very nice plugin for showing cross platform Alerts!
But for this question, can we assume it can not use a UIAlertView (or some other top level MessageBox type call on other platforms) but needs to show a Message within a given subsection of the screen (i.e. on IPhone you would need to supply a UIView to the plugin which it will use to show the message within).
So, how would you set this up so the ViewModel knows what View to use as its display container?
As a specific example, if I wanted an Error Service, as so -
public interface IErrorPFService
{
void Show();
void Hide();
void SetErrors(List<Error> errors);
}
and I create a platform specific implementation for it.
If I inject this into my ViewModel so it can control Error Show/Hide/Set how do I tell it the UIView (or equivalent) that I want my Errors to show within?
Can I just expose the IErrorPFService field as a public property and do -
MyViewModel.ErrorPFService = new ErrorPFService(View);
in my ViewDidLoad ...
Or is this coupled incorrectly vs Mvvm Practice?

I would expect the ViewModel to subscribe itself to the ErrorService.
When receiving a message it would expose it in a collection(?) and the View would bind to that collection.
This way the View is unknown to the service and the ViewModel has the chance to influence the View contrary to your solution.

It would help if you could give an example for the scenario you are describing.
Sometimes, the way you visually want to display something might not be the best way, so if it's possible for you, you might find a different and simpler way, which spares you from having to find a solution regarding what you are describing.
Generally, I always do the best I can to avoid the idea of having to actually pass a 'view' or an abstraction of it, from the view-model to view. Also, cross-platform wise, things can work very different in terms of UI interaction. You can find yourself in a situation when things are complicated just because UI works differently than what you expected.
But let's try find another perspective:
At any given point, the view knows what data \ feature it's displaying. So when you are calling from the view-model an user interaction action (by a service, property change, event, etc) the view should 'expect' it.
For example, the platform specific user interaction implementation is able to get the currently displayed top-view and interact it in a platform specific manner or based a relationship. In your example, the message-box can be displayed in a specific sub-view of the top level view.
In advanced scenarios, I guess you could try to create a cross-platform approach for this, but you should try to put in balance all the abstraction you want to create just for that. Think about doing this as a plan ... Z. If possible. Again, giving an example might help.

Related

Best practice so switch between a grid and list layout at runtime

Im currently working on a project where I want to the user to be able to chose between two layouts (list and grid) at runtime. I was searching for examples in the UI5 documentation (Sample Apps) and on GitHub, I did not find examples for how to to this or best practice examples. So I thought about how I could achieve this behaviour and had multiple ideas, but somehow none of them feels like doing this would be best practice.
Idea 1 - Destroy the "old" controls and generate the new controls inside the Controller
My first idea was to destory the controls I do not longer need. For example if the user wants to switch to the grid layout, the list and every control related it to it gets destoyed. In the controller the needed controls for the grid are created and then rendered in the view. In my eyes this would mix up view and controller logic inside the controller and does not feel like best practice
Idea 2 - Create two views and switch between them
My second idea was to create two views, each for the layout I need and switch between them. This would mean a lot of code replication in both the controller and the view. Does not feel like this would be the right way.
So I would be glad if you have own experience on this or if there is really something like a best practice for such a behaviour.
Thank you and kind regards!
I would say, idea 2 because of the following reasons:
It is best practice to work according to the MVC methodology which means separating logic, view and data. Since the controls define your view it is best to instantiate your controls in the files that are meant for it (the XML Views).
Performance: Destroying all controls means that if the user decides to switch between views, the controls have to be re-instantiated by the controller every time. This is, even though you probably won't notice it, not performant.
You don't need code replication: The argument of code replication is not necessarily true. If you can execute the same actions in the list and grid-view, it should be enough to just link the controller to both views and in that case you'll hardly have to replicate any code. Just make sure that you split your logic in enough functions. That way you might need to write some extra public functions to handle events, but not much more.

Navigating hierarchical data, FrameAdapter, Frame control

I want to implement navigating a tree structure like it is done in e.g. the WinRT file picker. I then want to be able to drop this behavior as part of any page.
My current attempt, is to try and register a secondary FrameAdapter/INavigationService in the container and use that for a frame that is different from the app root frame. So far, I could not get it to work.
My motivation behind that, is, that I do not want to reimplement sth. that the INavigationService already provides.
Basic structure:
ShellView that represents the general app layout (header, footer, navigation) and is currently an OneActive conductor.
Frame control (x:Name="ActiveItem") on the ShellView inside which the hierarchical navigation should occur
The chosen conductor has no relevance yet, since I'll probably have to nest the FrameControl inside another view later to really set up a MDI interface. I'll will want to have multiple screens that should be able to hierarchically navigate
I could not find a CM WP7 example of such a scenario
Can you help me out here?
My problems so far:
How do I access the container from a view code-behind without resorting to using the Application.Current. I figured, it is in the code-behind where I would want to setup the secondary FrameAdapter, since it is here that I have access to the FrameControl
How do I setup the INavigationService so that the initial loading by CM (populating the ActiveItem) is registered with it. There does not seem to be a navigation event for this initial display of the ActiveItem.
Many thanks in advance,
Tobias
PS: I have cross-posted to the Caliburn Micro discussions (Discussion over at CodePlex CM)

Opening save file dialog in MVVM using OnPropertyChange is Ok or Not

I am developing painting application in which i need to save my painting.
To save i need to show save file dialog , As i am implementing MVVM pattern i can't directly use event handler.
But while implementing i thought of using PropertyChanged event directoly.
I have implemented INotifyPropertyChanged in ViewModel , I have bind all commands.
In save command in ViewModel i have called
OnPropertyChanged("Show Save Dialog"); // in ViewModel
and in code behind of user control I have added event handler as
ViewModel.PropertyChanged += new // in code behind of user control
System.ComponentModel.PropertyChangedEventHandler(ViewModel_PropertyChanged);
and in ViewModel_PropertyChanged i have
switch (e.PropertyName ) // in code behind of user control
{
case "Show Save Dialog": ShowSaveFileDialog();// this function shows dialog.
break;
}
This works fine in my situation but I don't know the dark side of this implementation.
Is it right ????
Right? There is no right or wrong, only the best choice at the current time. The only way for purists would be to abstract away the process of gaining such input from the user behind an interface, then create a View class which serves this interface and inject it somehow (IoC/DI, or perhaps by composition in the xaml if your ViewModels are instantiated that way).
Personally, I wouldn't spend too much time worrying about this, unless you must worry about this. I've done it both ways. For your average MVVM app, I think it is no great crime to just use a MessageBox, OpenFileDialog, etc. For heavily tested apps, you'll need to abstract it away. And there are other situations that demand it as well. For example, I have code that exists in an application and in a Visual Studio extension. VS has its own dialog types which should be used instead of, say, MessageBox. So abstraction is appropriate. But I wouldn't invest the work unless I had a reason to.
Why don't you just create a custom event? Something like this in your ViewModel:
public event EventHandler<EventArgs> ShowSaveDialog;
and then use
ViewModel.ShowSaveDialog += OnShowSaveDialog;
private void OnShowSaveDialog(object sender, EventArgs e){
//handle the event
}
I wouldn't just "abuse" PropertyChanged like that. There's probably nothing wrong with your implementation, it just doesn't feel right. Also, you're using magic strings, but if you have a custom event it's much more declarative, and other users of your code will immediately figure out there is a way to subscribe to this event.
If you need to pass extra information, then make a implementation of EventArgs and add the properties you need.
Well as Will said there is no right or wrong ... only best choices!
Personally, I tend more to the purist side and try to architect a system to have a clear separation of concerns ... but that's just me!
Here is an answer I gave to a post dealing with the same problem as yours. There I show the two current approaches floating around when you want to keep your view model clean of any view code.
But again, choose the way that best fits your needs/preferences!

How do I implement base view functionality on Windows Phone 7?

Lets say that on all my views, or generally at any time in my app, I want to be able to show an error message popup, and it always looks the same. How do I do that?
First thought is having all my view models extend a base view model which facilitates these things, but after that, do I have this base view model actually create the UI widgets and display them?
thanks,
Mark
If you've got some common functionality that you want to provide across a range of views, then you can implement a base class that inherits from the PhoneApplicationPage, and then derive all your classes from that class instead. The XAML for your pages then looks like this:
<local:BasePage xmlns ...
xmlns:local="clr-namespace:MyNamespace"
x:Class="MyNamespace.MyPage">
However, you will not be able to define common UI components in the XAML for your base page. If you wanted to have common UI components you would have create them manually in the code-behind for the base page, perhaps in a handler for the Loaded event, but I think a better solution would be to provide your common UI in a UserControl, which you then add to each of your pages.
If you want to show a Toast or Message Box, then I would recommend the ToastRequestTrigger and MessageBoxRequestTrigger from the Silverlight Toolkit as described in the patterns & practices WP7 Developer Guide.
you could probably define an event on base view model, which is fired inside view model whenever an error occurs, then in view, you can subscribe to this event and display the popup. You can carry error context in EventArgs of the fired event.
Additionally you could unify the logic for displaying the popup but that's probably another story :)
This is testable and nicely decoupled from the view.
Hope this helps,
Robert

Where to store "global" data in Eclipse RCP Application?

I'm a beginner with Eclipse RCP and I'm trying to build an application for myself to give it a go. I'm confused about how one actually goes about handling model objects. None of the examples I can find deal with the problem I'm having, so I suspect I'm going about it the wrong way.
Say I need to initialise the application with a class that holds authenticated user info. I used my WorkbenchWindowAdvisor (wrong place?) to perform some initialisation (e.g. authentication) to decide what view to show. Once that's done, a view is shown. Now, that view also needs access to the user info I had earlier retrieved/produced.
The question is, how is that view supposed to get that data? The view is wired up in the plugin.xml. I don't see any way I can give the data to the view. So I assume the view has to retrieve it somehow. But what's the proper place for it to retrieve it from? I thought of putting static variables in the IApplication implementation, but that felt wrong. Any advice or pointers much appreciated. Thanks.
The problem you are facing here is in my opinion not RCP related. Its more an architectural problem. Your view is wired with business logicand!
The solution can be done by two (common) design-patterns:
Model-View-Controler (MVC)
Model-View-Presenter (MVP)
You can find plenty information about this in the web. I am going to point a possible solution for your particular problem using MVP.
You will need to create several projects. One is of course an RCP plugin, lets call it rcp.view. Now you create another one, which doesnt make UI contributions (only org.eclipse.core.runtime to start with) and call it rcp.presenter. To simplify things, this plugin will also be the model for now.
Next steps:
Add the rcp.presenter to the
dependencies of rcp.view (its
important that the presenter has no
reference to the view)
Export all packages that you are
going to create in the rcp.presenter
so they are visible
In rcp.presenter create an interface
IPerspective that has some methods
like (showLogiDialog(), showAdministratorViews(User user), showStandardViews(User user))
Create a class PerspectivePresenter that takes IPerspective in the constructor and saves it in an attribute
In rcp.view go to your Perspective, implement your interface IPerspective, and in the constructor create a new reference presenter = new PerspectivePresenter(this)
call presenter.load() and implenent
this in the presenter maybe like this
code:
public void load()
{
User user = view.showLoginDialog(); // returns a user with the provided name/pw
user.login(); // login to system/database
if(user.isAdministrator())
view.showAdministratorViews(user);
else
view.showStandardViews(user);
}
As you can see, the view just creates a reference to the presenter, which is responsible for all the business logic, and the presenter tells the view what to display. So in your Perspective you implement those interface functions and in each one you can set up your Perspective in a different way.
For each View it goes in the same way, you will need a presenter for the view which performs operations and tells the view (using the interface) what to display and passing down the final data. The view doesnt care about the logic. This is also very usefull when using JFace-Databindings (then only bound data is passed to the view).
For example, the WorkbenchWindowAdisor will just create everything that is needed in the application. Other views, perspectives, then can enable/disable menus and so on depending on the data they got (like when isAdministrator you might want to enable an special adminMenu).
I know this is quite a heavy approach, but the Eclipse RCP is designed for big (as the name says rich) applications. So you should spend some time in the right architecture. My first RCP app was like you described...I never knew where to store things and how to handle all the references. At my work I learned about MVP (and I am still learning). It takes a while to understand the concept but its worth it.
You might want to look at my second post at this question to get another idea on how you could structure your plugins.