Based from a video from Brian Lagunas (YouTube Link) I started using Prism 6. I am a little bit confused, where the constructor of the MainWindowViewModel is getting called. I nearly copied his project and can't find the part. If i set a break point in the constructor, it never gets there.
Was he no showing something in the video or something?
If you have a look at the code for this presentation, you can see that Brian is using Prism's attached dependency property to couple view and viewmodel through the ViewModelLocator.
prism:ViewModelLocator.AutoWireViewModel="True"
In the video around 33:00 he gives the full explanation how this ViewModelLocator works: first it builds the viewmodel name out of the view's name through convention. Then it either resolves this name to a type through an IoC container or reflection. IoC is pretty straight forward: give a type or name and it will give you an instance. For the reflection part (when you run without a container), Prism uses the Activator type to create a new instance.
In the final code available on GitHub, Brian is using Unity as IoC container. Custom mappings for his sub-views (ViewA/ViewB) are made in the Bootstrapper. As there is no custom mapping for MainViewModel, following process happens:
The app starts with MainWindow as the startup window.
The attached property for the ViewModelLocator gets 'triggered', internal logic will map from MainWindow to MainWindowViewModel
As we're using Unity, the ViewModelLocator asks for an instance of the viewmodel
Unity will create a new MainWindowViewModel object and the constructor will get hit
So you won't see new xxxViewModel() in code, but it does get created. This means you have much greater flexibility over hardcoded object creation when it comes down to adding dependencies.
Related
I'm working on an editor to make changes to a list of emf objects. What I want is every time I modify those emf objects, my editor is to be refreshed to reflect the changes.
The approach I tried before was having a wrapper object over the said emf object (because I don't know how I can or should modify the emf-generated source code) to contain the editor needs to be refresh. The changes will be made on top of that wrapper object, and propertychangelistener is to be dispatched after emf object have been changed. However this solution is very ugly because:
Each object will need to obtain the reference to the editor itself, introducing a reference dependency
Having a separate overlay object like that introduces complication into maintaining the code
What is the right way to do it?
I think of adding binding framework to handle model object changes
You may want to look at following tutorial as a starting point.
http://www.vogella.com/articles/EclipseDataBinding/article.html
I'm developing a web app for different formfactors. Each has its own client factory to create formfactor dependent views. Everythings works fine so far but I'm stuck when it comes to the Editor Framework.
To make use of the framework I have to declare a marker interface like so:
interface Driver extends SimpleBeanEditorDriver<User, UserEditor> {}
Since this happens in my formfactor agnostic activity I want the type UserEditor to refer to the actual implementation based on the formfactor, i.e. UserEditorPhone, UserEditorTablet, UserEditorYouNameIt.
To no avail I tried using deferred binding in module.gwt.xml:
<replace-with class="com.example.client.desktop.UserEditorDesktop">
<when-type-is class="com.example.client.view.UserEditor"/>
</replace-with>
Any ideas on what I'm missing and how to avoid having a one-to-one-relationship between formfactors and UserEditor-activities?
You'll want your formfactor-agnostic activity to only know about SimpleBeanEditorDriver<User, ?>, and move the Driver interface into each one of UserEditorDesktop, UserEditorTable and UserEditorPhone.
The activity will then ask a formfact-dependent object (e.g. its view, if you use MVP and the activity is the presenter) for an instance of the editor driver rather than using GWT.create() directly.
(I can give code sample if you detail how your code is organized: are you using MVP? is the editor your view? how's it instantiated? etc.)
I am writing a GWT MVP application using the gwt-platform library (very nice once you get used to it). My issue occurs when my presenter attempts to update the contents of a Listbox. The problem occurs on line 66 of the below file:
https://github.com/dartmanx/mapmaker2/blob/master/src/main/java/org/jason/mapmaker/client/presenter/MapmakerStackPanelPresenter2.java
I am sure that the application is calling the onSuccess() method (a breakpoint in the debugger works), and that the result is populated.
One thing I've noticed is that the associated view, MapmakerStackPanelViewImpl2.java, seems to be initialized twice. I find myself wondering if I'm trying to update a control on that view that is not attached to the actual user interface. That file is here:
https://github.com/dartmanx/mapmaker2/blob/master/src/main/java/org/jason/mapmaker/client/view/MapmakerStackPanelView2.java
Any help would be appreciated.
The problem was that there were two copies of the view floating around. I used Gin to inject the view into the constructor of the presenter, and problem went away.
With the MVVM pattern, how does one go about dynamically binding
an ICommand to the click event of a hyperlink inside of a
RichTextBox?
It's a few steps to get there, but you can do it.
You have to use a bindable rich text box, rather than the one that comes with WPF which is not something you can bind. Details here: http://michaelsync.net/2009/06/09/bindable-wpf-richtext-editor-with-xamlhtml-convertor
Once you have that, you'll have a Rich Text Editor that you can bind to a FlowDocument in your ViewModel.
When your FlowDocument is created, hookup a handler for the Hyperlink.ClickEvent in your ViewModel:
Here's the call that adds the handler to the FlowDoc
TheDocument.AddHandler(Hyperlink.ClickEvent,
new RoutedEventHandler(HandleHyperlinkClick));
//Here's the handler definition
private void HandleHyperlinkClick(object sender, RoutedEventArgs args)
{
Hyperlink link = args.Source as Hyperlink;
//...
}
This is the only thing I've ever seen done. FlowDocuments are a little strange because they are sort of a data type and sort of a visual element so in some sense it feels wrong to have it reside in your ViewModel, but this is the way to go.
You find a lot scenarios where it is not possible to use wpf data binding. In these scenarios you can create a new control (e.g. inherit from RichTextBox) and provide the missing dependency properties so you can use data binding.
However, creating a new control to handle simple scenarios is inefficient. It's not forbidden to implement code in the View's code behind file and this makes often more sense than creating a new control.
A concrete example how this can be done is shown in the ViewModel sample of the project:
WPF Application Framework (WAF)
http://waf.codeplex.com
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.