Xamarin FreshMVVM PublicKeyToken=null not found' - xamarin.forms

I'm working on a Xamarin forms app and i am using fresh MVVM framework.
i added a button to a ContentPage that needs to open a new page.
the following error is:
System.Exception: 'Bux_Management.Pages.JournalsOverviewPage, Bux Management, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null not found'
my button in Xaml
<Button Text="Go to journal overview page" Command="{Binding ShowJournalOverviewPage}"/>
my command in my PageModel which inherits from FreshBasePageModel
public Command ShowJournalOverviewPage
{
get
{
return new Command(async () => {
await CoreMethods.PushPageModel<JournalsOverviewPageModel>(null);
});
}
}
my page models are in de folder "PageModels" and they inherit from "FreshBasePageModel"
my pages are in the folder "Pages" and they inherit from "ContentPage"
Thanks in advance,

Yes indeed it was a problem with the namespaces, first i used ViewModels and View as folders and changed it later to PageModel and Pages

Related

Xamarin forms how to pass parameters from page to tabbed page

I have problem to pass parameter from page. Goal is that after login wanna show logged user info in tabbed page. Can you help me how to pass parameter from page to tabbed page.
Thank you
Solution is
Login Page
await Navigation.PushAsync(new TabbedPage1("Name"));
TabbedPage
<local:Page1 Title="Page1">
<Label x:Name="lblfirstname"/>
</local:Page1>
public partial class TabbedPage1 : TabbedPage
{
public TabbedPage1(string firstname) {
InitializeComponent();
lblfirstname.Text = firstname;
}
}
There are many solutions, but it's depend on your implementation.
The simplest is use MessagingCenter . Your tabbed page can subscribe and your page can publish all necessary parameters.

Xamarin automatic sign-in credentials for Google Play's pre-launch report

I am building an Android application with Xamarin Forms 3 in Visual Studio 2017 and publishing to Google Play. Google Play offers automated testing (pre-launch report) but it cannot get past my sign-in screen.
Google Play has a place to enter the "username resource name", "password resource name", and "sign-in button resource name". I provided the Xamarin x:name for each control (txtEmail, txtPass, and btnSignIn), but apparently that is not correct, because the automated tester still can't get in and isn't even trying.
Here is my SignIn.xaml:
<Entry x:Name="txtEmail" Placeholder="email address" Keyboard="Email" />
<Entry x:Name="txtPass" IsPassword="True" />
<Button x:Name="btnSignIn" Text="Sign In" Clicked="OnSignInClicked" />
I've found these SO questions (here, here, and here) but they do not address my question from within a Xamarin Forms context. The first link seems particularly helpful but I do not know where to put that XML code.
It seems to me that Xamarin/C# is "compiled" into Android code and generates these XML files. How can I work with this process?
I understand an .APK file is just a ZIP file. Renaming the APK file I send to Google Play to .zip I'm able to browse the contents, but I do not see any XML code that makes sense.
For the moment, I added an extra "demo" button that, on click, puts a username and password into the fields and clicks the Sign In button. Google's automated tester likes this and can get in, but it's a terrible idea for human testing and I'd like to remove this workaround.
I've faced the same issue recently. I submitted an alpha build, enabled pre-launch report and got a policy violation error saying, that sign-in credentials are not provided. As it's stated in the question, I should have provided resource names along with the test credentials, but it wasn't obvious how to do it in Xamarin.Forms project. Nevertheless, I was able to workaround it using renderers. I know, it's a bit extreme to create a separate renderer and a control just to set id, but I really didn't want to change UI significantly, so, I created 3 empty controls:
public class UsernameEntry : Entry { }
public class PasswordEntry : Entry { }
public class LoginButton : Button { }
And used each of them in corresponding places on the login screen, instead of plain entries and the button.
Then I added ids.xml file into the Android project (Resource/values/ids.xml) and added 3 ids, one for every control:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="username_entry" type="id"/>
<item name="password_entry" type="id"/>
<item name="login_button" type="id"/>
</resources>
Finally, I created 3 renderers in the native Android project, one for each control. For example, this is how the UsernameEntryRenderer looks:
[assembly: ExportRenderer(typeof(UsernameEntry), typeof(UsernameEntryRenderer))]
namespace Android.Renderers
{
public class UsernameEntryRenderer : EntryRenderer
{
public UsernameEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
// here I can reference the id created previously in ids.xml file
// and set the native android id property
Control.Id = Resource.Id.username_entry;
}
}
}
}
This is not the perfect way, but it worked well in my case. I didn't need to change the UI drastically or to introduce some hidden UI elements. Hopefully, this will be helpful for anyone facing similar problem.
Inspired by Yehor's answer, I was able to come up with a solution that uses Xamarin Effects without using custom controls.
First add ids.xml file into the Android project (Resource/values/ids.xml) and add 3 ids, one for every control. Make sure the Build action is set to AndroidResource and the Custom Tool is set to MSBuild:UpdateGeneratedFiles so the C# files can be generated automatically for the styles:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="username_entry" type="id"/>
<item name="password_entry" type="id"/>
<item name="login_button" type="id"/>
</resources>
Then define an enum so the effects can be defined easily:
public enum CustomIdType
{
None,
Username,
Password,
LoginButton
}
For the Android custom renderer, implement the following assign the android ID based on the custom effects.
[assembly: ResolutionGroupName("CustomRendererHandler")]
[assembly: ExportEffect(typeof(AndroidCustomIdEffect), "CustomIdEffect")]
namespace YOUR_ANDROID_NAMESPACE
{
public class AndroidCustomIdEffect : PlatformEffect
{
protected override void OnAttached()
{
// get autofill effect
var effect = (CustomIdEffect)Element.Effects
.FirstOrDefault(e => e is CustomIdEffect);
// assign android ID if custom ID effect is not null
if (effect != null) {
switch (effect.Type) {
case CustomIdType.Username:
Control.Id = Resource.Id.username_entry;
break;
case CustomIdType.Password:
Control.Id = Resource.Id.password_entry;
break;
case CustomIdType.LoginButton:
Control.Id = Resource.Id.login_button;
break;
}
}
}
protected override void OnDetached()
{
}
}
}
Then define a Routing Effect in your shared code to consume the Android custom renderer:
public class CustomIdEffect : RoutingEffect
{
public CustomIdType Type { get; set; }
public CustomIdEffect() : base("CustomRendererHandler." + nameof(CustomIdEffect))
{
}
}
Finally, to consume the Effects in your login page, simply add the Effects to the controls in XAML:
<Entry PlaceHolder="Enter Username">
<Entry.Effects>
<local:CustomIdEffect Type="Username"/>
</Entry.Effects>
</Entry>
<Entry PlaceHolder="Enter Password">
<Entry.Effects>
<local:CustomIdEffect Type="Password"/>
</Entry.Effects>
</Entry>
<Button Text="Login">
<Button.Effects>
<local:CustomIdEffect Type="LoginButton"/>
</Button.Effects>
</Button>
After that Google Pre-launch Report should be able to get pass the login screen if you provide the right sign-in credentials.

How do I close an MvvmCross MasterDetail page?

I would like my app to show a Login page, then a MasterDetail page with a 'hamburger' menu. On the hamburger menu I want a Log Out entry that closes the Master Detail and shows the Login page again. I have all but the log out part working.
I have copied code from the MvvmCross Playgrounds sample, specifically the MixedNavFirstPage (which fakes a login procedure), MixedNavMasterDetailPage (the 'hamburger menu'), and MixedNavMasterRootContentPage.
If I try to close the MixedNavMasterDetailPage with await _navigationService.Close(this) then I get a null reference exception in MvxFormsPagePresenter.CloseMasterDetailPage()
This question How to Exit (or Navigate out of )a MasterDetail page to a simple ContentPage in Xamarin. Forms? covers what I want to do in straight Xamarin.Forms, I'm just not sure how to do the equivalent in MvvmCross.
In your LoginPage add the MvxContentPagePresentation attribute NoHistory = true
Then simply navigate to the login page, and when the user has logged in, navigate to your MasterDetail page also with NoHistory = true.
When the user logs out again, simply navigate to your LoginPage, and as the NoHistory = true the MasterDetail will be removed completely.
[MvxContentPagePresentation(WrapInNavigationPage = false, NoHistory = true)]
public partial class LoginPage : MvxContentPage<LoginViewModel>
{
public LoginPage()
{
InitializeComponent();
}
}

How can I render Razor page from Assembly

UPDATE1
I've added RazorGenerator and etc...
After set custom tools, I've seen generated code for my razor pages.
Added this code in assembly
public class MyAreaRegistration : AreaRegistration
{
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute("Dictionary_default", "MyDictionary/{Action}/", new { controller = "DictionaryControllerBase", action = "Index" });
}
public override string AreaName
{
get { return "MyDictionary"; }
}
#endregion
}
But when I open page by url /MyDictionary, i see "Unable to find the resource."
NOTE I use in my project MVC3 and Spring.Net
I use one controller (base controller) in another Assembly with razor pages.
In my project I make controller inherited from base controller, just it make some settings. But razor pages I wish to use from assembly.
How can I do it?
You could the RazorGenerator extension. I have detailed how this can be achieved in the following post. The idea is that the RazorGenerator extension would create a corresponding .cs file for each Razor view and it will update it every-time you make a change to the corresponding view. This way the Razor views will be precompiled in the class library along with their respective controllers and view models. The RazorGenerator.Mvc NuGet will then register a custom virtual path provider which will take care of resolving those views.

Dynamic Stylesheets Using Razor

How can I use Razor in CSS files?
I'm using Razor View Engine for some time and I was curious about using it on style sheets. I can use Razor in <style> blocks of .cshtml files but I was wondering if I can use it in external .css files also (would like to have a .cscss format). So I googled it and found two things:
The first one is LESS: "The dynamic stylesheet language". It seems easy-to-use and powerful with all the features but I need Razor-C#, really.
The second is Dynamic CSS Using Razor Engine, a CodeProject article which is more like what I want but it has no caching or pre-compiling support (by "no support" I meant the writer didn't mention these aspects). I also would like to have some syntax highlighting in Visual Studio but this is secondary.
So, how can I write Razor in CSS files with minimum performance cost and preferably with syntax highlighting?
Is there a "more complete" project for that?
Can I improve the above project to achieve caching/compiling? If so, how?
As a side note:
I found a project called RazorJS. It's like the Javascript version of the same thing I want for CSS with its caching support. I'm mentioning this just to clarify my needs. I don't need to use Razor in Javascript currently but I guess if I make it out with CSS, doing the same thing with Javascript wouldn't be too hard.
You could create a custom view engine:
public class CSSViewEngine : RazorViewEngine
{
public CSSViewEngine()
{
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.cscss",
"~/Views/Shared/{0}.cscss"
};
FileExtensions = new[] { "cscss" };
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
controllerContext.HttpContext.Response.ContentType = "text/css";
return base.CreateView(controllerContext, viewPath, masterPath);
}
}
and also register it with a custom extension in Application_Start:
ViewEngines.Engines.Add(new CSSViewEngine());
RazorCodeLanguage.Languages.Add("cscss", new CSharpRazorCodeLanguage());
WebPageHttpHandler.RegisterExtension("cscss");
and inside web.config associate the extension with a build provider:
<compilation debug="true" targetFramework="4.0">
<assemblies>
...
</assemblies>
<buildProviders>
<add extension=".cscss" type="System.Web.WebPages.Razor.RazorBuildProvider, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</buildProviders>
</compilation>
[note, if you get an assembly binding error you might need to change the version number in the extension type to match your version of the Razor engine. You can check which version you are using by looking at the properties of your reference to the System.Web.WebPages.Razor assembly in your project]
And the last step is to have some controller:
public class StylesController : Controller
{
public ActionResult Foo()
{
var model = new MyViewModel
{
Date = DateTime.Now
};
return View(model);
}
}
and a corresponding view: (~/Views/Styles/Foo.cscss):
#model AppName.Models.MyViewModel
/** This file was generated on #Model.Date **/
body {
background-color: Red;
}
which could now be included as a style in the Layout:
<link href="#Url.Action("Foo", "Styles")" rel="stylesheet" type="text/css" />

Resources