Uno Platform ViewModelLocator - autofac

I'm testing uno platform solution to see if it's flexible enough and can integrate pre existing autofac (6.2.0) and Autofac.Extras.CommonServiceLocator(6.0.1) stuff in it.
I want to add the ViewModelLocator to auto resolve view models. it's working with UWP and wpf project, but not with droid or WASM.
I added in shared app.xaml the resource
<Application
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<!-- #Region MVM light view model locator -->
<ResourceDictionary>
<local:ViewModelLocator x:Key="ViewModelLocator" d:IsDataSource="True" />
</ResourceDictionary>
<!-- #Endregion -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
In the mainpage.xaml
DataContext="{Binding [TestViewModel], Source={StaticResource ViewModelLocator}}"
whit this configuration the constructor is called at startup where I also want to set up Inversion of control stuff
public ViewModelLocator()
{
this._container = IOCContainerConfig.Configure();
var serviceLocator = new AutofacServiceLocator(this._container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
//this._dbContext = serviceLocator.GetInstance<IContext>();
//TestDbConnection(this._dbContext);
}
As said this is not working with other kind of projects like droid or wasm the constructor of the locator is never called but I don-t have errors, just page is loaded without the viewmodel behind.
Any ideas or tips to make it working for all projects?

Depending on the type of resource, Uno Platform is initializing some resources in a ResourceDictionary lazily only when they are accessed. This is done as a performance optimization.
To guarantee that the ViewModelLocator constructor is always called on all platforms, it may be better to call it from code, eg from the App constructor in App.xaml.cs.

Related

Xamarin Forms XAML Design Instance

Is there a way to enable design context in Xamarin Forms XAML pages to enable intellisense? It works in WPF but for years I couldn't get it to work in Xamarin Forms.
So if you compile your xaml by setting the attribute in code somewhere, and then include the xaml snippet below, you can use design time data contexts and get the intellisense.
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace MySpace
{
public partial class App {}
}
<Page
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d ="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=list:TestViewModel}"
xmlns:list="clr-namespace:PolyhydraGames.Test.ViewModels"
.../>
Normally you should get it by default. Otherwise try Ctrl + Space. You do not need any additional code. Note it will not show you the intenseness for binding objects but all the design time elements.

Add custom properties to eclipse's project class

I have a custom project nature and created a new project that has this new custom nature.
What I am trying to do now, is extend the properties of that project, so when it is selected e.g. in package explorer view, not only the standard project properties are shown in the (standard) property-view but also customized ones (like the nature of the selected project - but only for a project that has my custom nature)
Is this possible with standard eclipse extension points?
I have doubts since I don't have my own class where I could register a property-descriptor, just a new nature.
You should be able to define a project properties page without a project class, as I've done in the Haskell plugin:
<page
name="%projectFlagsPP_name"
class="net.sf.eclipsefp.haskell.ui.properties.UserFlagsPP"
id="net.sf.eclipsefp.haskell.ui.properties.UserFlagsPP">
<filter
name="nature"
value="net.sf.eclipsefp.haskell.core.project.HaskellNature">
</filter>
<filter
name="open"
value="true">
</filter>
<enabledWhen>
<adapt type="org.eclipse.core.resources.IProject" />
</enabledWhen>
</page>
And then the java code starts like:
public class UserFlagsPP extends PropertyPage implements
IWorkbenchPreferencePage {
This says that the property page will appear for a IProject that has the Haskell Nature...

GWT Internationalization to Arabic (RTL language)?

I have a problem (supposed to be a GWT feature) when i internationalize my Webapp to a RTL language. Basically, the GWT feature mirrors the interface to RTL and I don't want that to happen.
How can I prevent GWT from automatically mirror my interface and just keep translated strings?
Here is my *.gwt.xml code:
<!DOCTYPE ... >
<module rename-to='blah'>
<inherits name='com.google.gwt.user.User' />
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name="com.google.gwt.i18n.I18N"/>
<inherits name="com.google.gwt.json.JSON" />
<inherits name="com.google.gwt.user.Debug"/>
<extend-property name="locale" values="pt"/>
<extend-property name="locale" values="es"/>
<extend-property name="locale" values="ar"/>
<source path="client"/>
<source path="shared"/>
<entry-point
class="EntryPoint"/>
<!-- Remote services -->
</module>
Regards
GWT Support Both RTL & LTR Langauages
If you want to have LTR(Left to Right) theme then use <inherits name="com.google.gwt.user.theme.chrome.Chrome"/> (default theme) in *.gwt.xml
If you want to have RTL(Right to Left) theme then use <inherits name="com.google.gwt.user.theme.chrome.ChromeRTL"/>in *.gwt.xml
In your case If you dont want GWT feature mirrors the interface to RTL then use <inherits name="com.google.gwt.user.theme.chrome.Chrome"/>
You can create a class called "CldrImpl_ar" in your project under the "com.google.gwt.i18n.client.impl.cldr" package (you will have to create this package yourself). The class would contain the following code:
package com.google.gwt.i18n.client.impl.cldr;
import com.google.gwt.i18n.client.impl.CldrImpl;
public class CldrImpl_ar extends CldrImpl {
#Override
public boolean isRTL() {
return false;
}
}
This class already exists in the GWT library code but the return value is true there. Once this standalone class is created, it takes precedence over the one in the GWT library, thus achieving the "overwriting" effect.
This does exactly what you are looking for:
No automatic mirror effect when using Arabic
Just use the translated strings
The end result is probably not the best experience for the Arabic user, but it does save significant development time if supporting right-to-left is not a high priority for your project..
Unfortunally this is a feature of a number of the GWT widgets. These widgets call LocaleInfo.getCurrentLocale().isRTL() internally and even if you would somehow change the return value of this call it would then disable the rtl for text also. So that's not an option.
I guess you have 2 options. Firstly, not use widgets that use the RTL check or secondly, when adding a widget check for isRTL yourself and add it in the opposite direction. For example if you add a widget to the WEST, add it to the EAST when isRTL() is true. Both options are not optimal, but I see no other solution.
We had the same issue. With GWT 2.6.x, you can accomplish this by using deferred binding to force the value of LocaleInfo.isRTL() to false:
<replace-with class="org.activityinfo.i18n.shared.CldrImplLtr">
<when-type-is class="com.google.gwt.i18n.client.impl.CldrImpl"/>
<when-property-is name="locale" value="ar" />
</replace-with>
You can leave out the <when-property-is tag if you want to force this
for all locales.
And then provide a simple CldrImplLtr class:
public class CldrImplLtr extends CldrImpl {
#Override
public boolean isRTL() { return false; }
}
There seem to a few funny things, but it seems to be more manageable than supporting a full Right-to-left mirroring of the interface.

Using mgwt for desktop and mobile applications

I have an application written in GWT. I want to be able to provide a subset of the same application for use when the site is opened in mobile browsers, and have been looking at mgwt as a way of achieving this.
The way I am expecting it to work is that I will augment my existing GWT application project with mgwt code (with some logic sharing) resulting in two entry points. My question is how to manage this given a single html page? I have seen the approach described in this article and was wondering whether that will work well with mgwt or whether there should be another pattern I should be considering?
I don't think you need 2 entry points. As kiran said above, you should reuse all the code except the view components. In case you used the GWT Activities and Places module, the view components should be completely decoupled from the rest of the code.
In this case you can use the the GWT.create method associated with the correct definitions in the module xml definition:
//in your entry point:
private IClientFactory clientFactory = GWT.create(IClientFactory.class);
//in your module xml definition:
<replace-with class="com.vv.xui.client.DesktopClientFactory">
<when-type-is class="com.vv.xui.client.IClientFactory" />
<when-property-is name="formfactor" value="desktop"/>
</replace-with>
<replace-with class="com.vv.xui.client.MobileClientFactory">
<when-type-is class="com.vv.xui.client.IClientFactory" />
<when-property-is name="formfactor" value="mobile"/>
</replace-with>
The form formfactor property can be defined as in this example:
https://code.google.com/p/gwt-cx/source/browse/trunk/gwtcx/gwtcx-core/gwtcx-core-client/src/main/resources/com/gwtcx/FormFactor.gwt.xml
In your IClientFactory you will have something like this:
public interface IClientFactory {
IHomeView getHomeView();
ISearchView getSearchView();
...
}
Where IHomeView and ISearchView are the view interfaces implemented by the desktop and the mobile versions. In my case the View implementations are UiBinder components that implement the associated view interface.
In your DesktopClientFactory you will have something like this:
public class DesktopClientFactory implements IClientFactory {
private static final ISearchView searchView = new com.vv.xui.client.view.desktop.SearchView.SearchView();
#Override
public ISearchView getSearchView() {
return searchView;
}
...
}
In this way you don't need different entry points for mobile and desktop and can share all the code except the view components.
That pattern in the link pointing to MobileWebApp on googlecode is correct. Basically you have UI view interfaces in GWT which stick to MVP pattern recommended on GWT. Then you can do different implementations of the UI Views based on the screen resolutions available. Obviously you don't want the same screen lay outs on desktop and mobile. So you will need to redesign your views for different form factors and then call the correct implementations based on the form factor the device. Since you already have a gwt application, you can create views for mobile using mgwt and reuse the code that you already created. But still you will have to create new views for mobile using mgwt, it wont be a straight forward replace.

GWT: formfactor dependent editor

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.)