Mvvmcross: Text format binding with MvxLang - xamarin

I am building a native Xamarin app, and I am using Mvvmcross to do it. It is a really nice tool but I am still learning about how it works.
I found in the documentation yould could do the following thing with binding:
local:MvxBind="Text Format('Line: {0}', Line.Name)"
Here your binding the Testclass.Name variable with the format, so the result will be
Line: TestName
Now I want to do the same thing but also taking in a count the translation for Line:. So normally for translation you do the following.
local:MvxLang="Text Line_Label"
So my idea was to do something like this:
local:MvxLang="Text Format('{0}{1}', Line_Label, Line.Name)"
But it doesn't work like this. Does anybody have an idea if this is possible yet and how?

Use Tibet binding with local:MvxBind. Let's assume, that you have:
BaseViewModel.cs
public abstract class BaseViewModel : MvxViewModel
{
public IMvxLanguageBinder TextSource
{
get
{
return new MvxLanguageBinder(
Constants.GeneralNamespace,
GetType().Name);
}
}
}
MainViewModel.cs inheriting from BaseViewModel, with string property Name:
public string Name => "Radek";
TextProviderBuilder like in Stuart's N+1 days (no. 21) https://www.youtube.com/watch?v=VkxHtbJ_Tlk
JSON translation file with "MyLabel" key
{
"MyLabel" : "Your name:"
}
Answer: Then Android layout axml file will contain binding
local:MvxBind="Text Language(TextSource,'MyLabel') + ' ' + Name; Click NextCommand"
I don't know how to do this with local:MvxLang but the code above does the job :)

Related

OnChange in MudBlazor RadioButtonGroup

I am new to Blazor and MudBlazor. I am using a and I want to call an event when the selection changes. The documentation show there is a EventCallback method but there are no syntax examples. I have been searching a good part of the day but cannot find an example. Can anyone please share some simple code? I know I can bind to a variable, and I initially did that. What I want is to call code and do some different code based on the selected value. Seems to be easier to do in Blazor syntax vs MudBlazor.
I appreciate any help.
Thank you
<MudRadioGroup T="string" SelectedOption="#SelectedOption" SelectedOptionChanged="OnSelectedOptionChanged">
<MudRadio Option="#("Radio 1")" Color="Color.Primary">Primary</MudRadio>
<MudRadio Option="#("Radio 2")" Color="Color.Secondary">Secondary</MudRadio>
<MudRadio Option="#("Radio 3")">Default</MudRadio>
<MudRadio Option="#("Radio 4")" Color="Color.Primary" Disabled="true">Disabled</MudRadio>
</MudRadioGroup>
#code {
public string SelectedOption { get; set; }
private void OnSelectedOptionChanged(string selectedOption)
{
SelectedOption = selectedOption;
// call your stuff
}
}
https://try.mudblazor.com/snippet/mOQGYtGKUpgnQxqe

Persistent Storage using Application.Current.Properties not working

I'm trying to achieve a persistent storage in Xamarin.Forms. After researching in Xamarin.Forms, I decided to use Application.Current.Properties property.
It looks like it is working just only if the app still remains alive. If I close the app and start it again the Application.Current.Properties is empty.
Does anyone know if I'm doing something wrong? Can I achieve this feature in another way?
As usual, thanks guys.
I have had a ton of problems with Application.Current.Properties on Android. I highly suggest using Xamarin Settings plugin instead which I have never had any issues with. It is persistent even when the app is closed.
That being said Application.Current.Properties is supposed to work even when you close the app. Not sure why it wouldn't but it does not surprise me either.
*Edit: To use once it is installed, basically CrossSettings.Current is the plugin class that will do the work but the example just creates a separate property to access it. So create a new file, lets call it SettingsImplementation:
public static class SettingsImplementation {
#region Instance
private static Lazy<ISettings> _appSettings;
public static ISettings AppSettings {
get {
if(_appSettings == null) {
_appSettings = new Lazy<ISettings>(() => CrossSettings.Current, LazyThreadSafetyMode.PublicationOnly);
}
return _appSettings.Value;
}
set {
_appSettings = new Lazy<ISettings>(() => value, LazyThreadSafetyMode.PublicationOnly);
}
}
#endregion
private const string UserNameKey = "username_key"; //Key used to get your property
private static readonly string UserNameDefault = string.Empty; //Default value for your property if the key-value pair has not been created yet
public static string UserName {
get { return AppSettings.GetValueOrDefault<string>(UserNameKey, UserNameDefault); }
set { AppSettings.AddOrUpdateValue<string>(UserNameKey, value); }
}
}
Then to use that you would do this anywhere in your app:
SettingsImplementation.UserName = "something";
OR
string username = SettingsImplementation.UserName;
My own problem regarding this issue was due to me not explicitly saving the properties with the following line of code:
Application.Current.SavePropertiesAsync();
you can use Xamarin essentials "Preferences" instead:
Preferences.Set("Key", "Value");
Preferences.Get("Key", "Default");
I ran into the same issue.
The problem:
I was trying to throw complex objects into the Application Properties.
It turns out that the Properties can only take primitive data typs.
This Blog was very helpfull.
https://codemilltech.com/persist-whatever-you-want-with-xamarin-forms/

MVVMCross - Navigate ViewModel

When I try to open a new viewmodel I'm receiving the following error:
Failed to load ViewModel for type EasyBudget.Core.ViewModels.GridCategoryViewModel from locator MvxDefaultViewModelLocator
It´s also shows:
No symbols found.
And shows that cannot find or open the PDB file.
My viewmodel:
public class HomeViewModel
: MvxViewModel
{
private Cirrious.MvvmCross.ViewModels.MvxCommand _listCommandCategory;
public System.Windows.Input.ICommand ListCommandCategory
{
get
{
_listCommandCategory = _listCommandCategory ?? new Cirrious.MvvmCross.ViewModels.MvxCommand(DoListCategory);
return _listCommandCategory;
}
}
private void DoListCategory()
{
ShowViewModel<GridCategoryViewModel>();
}
}
And my other viewmodel:
public partial class GridCategoryView : MvxPhonePage
{
public GridCategoryView()
{
InitializeComponent();
}
}
Does anyone knows what may I be forgeting?
Best regards
Wilton Ruffato Wonrath
I believe the problem will most likely be somewhere in the construction of the ViewModel:
perhaps the constructor itself isn't public?
perhaps one or more of the parameters for the constructor couldn't be found?
perhaps some code inside the constructor has thrown an exception
Where you posted 'my other viewmodel' you actually posted code only for your other view. Can you post the code for the ViewModel that accompanies that view?
If you enable your debugger to break on all Exceptions, then this will possibly help you to find the problem that occurs during loading (inside https://github.com/slodge/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross/ViewModels/MvxDefaultViewModelLocator.cs).
If you want to a pdb for debugger symbols, then these can be found inside the folders of http://github.com/slodge/MvvmCross-Binaries - inside the VS2012/Release folders. We are also currently trying to work out how to distribute these via SymbolSource.org (first got the request/suggestion this week)
Finally, if you want to see trace from a Windows build and are using the release packages from nuget then you can do this by overriding CreateDebugTrace() in your Setup.cs file - e.g. try:
protected override IMvxTrace CreateDebugTrace()
{
return new MvxDebugTrace();
}
This will also allow you to add some debug trace to your Core code if you want to using:
Mvx.Trace(format, args...)
Mvx.Warning(format, args...)
Mvx.Error(format, args...)
Perhaps, you forgot about adding ViewModel type to your generic MvxPhonePage.
Try this:
public partial class GridCategoryView : MvxPhonePage<GridCategoryViewModel>

More convenient way to localize in windows phone apps

Currently, if you want to localize say Application Title in a windows phone app you would do this:
<TextBlock Text="{Binding LocalizedResources.ApplicationTitle,
Source={StaticResource LocalizedStrings}}" />
This is too long, and certain parts are repeated for each binding. Even if you were to rename LocalizedResources property to R and LocalizedStrings class to LS for example, some repetition still exist.
So I tried making a class that inherits from Binding class and implemented as follows:
public class LocalizedBinding : Binding {
public LocalizedBinding(string path) : base(path) {
Source = Application.Current.Resources["LocalizedStrings"];
}
}
The hope was to use it as follows:
<TextBlock Text="{b:LocalizedBinding LocalizedResources.ApplicationTitle}" />
However, the app crashes immediately upon start and I can't see any errors even in debugger. Any tips on how this might work?
Thanks
Edit:
Adding a parameterless constructor to LocalizedBinding and appending Path= to the binding fixes it.
This is fixed by adding a parameterless constructor to the LocalizedBinding class
public class LocalizedBinding : Binding {
public LocalizedBinding() {
Source = Application.Current.Resources["LocalizedStrings"];
}
public LocalizedBinding(string path) : base(path) {
Source = Application.Current.Resources["LocalizedStrings"];
}
}
You might try and put a Localization class into your App.xaml, then on Application_Launching check which language the user has set. Everywhere that you display the text you then refer to the App.xaml class.

Localization and binding don't work together

I'm developing my first app and I'm trying to make it multilanguage.
Using AppHub example and some other link I created my resource files, fixed binding strings on my components and set a settings page.
First problem I had was that menu items and appbar buttons couldn't use localization strings (project complained when launched) so I have:
TextBlocks and other components binded with localized strings
Appbar buttons and items localized manually with a procedure loading localized strings
Now that I have my settings page, one item user can change is language.
Well, correct CultureInfo is selected according to user selection and then I use
Thread.CurrentThread.CurrentUICulture = Settings.Language;
When I press back button and return to main page, appbar items are localized correctly, while everything else is not.
The only workaround (that I really don't like, it's just to understand) is this:
public MainPage()
{
Thread.CurrentThread.CurrentUICulture = Settings.Language;
InitializeComponent();
// Everything else I need here
}
so I have to set language before components are created to make it work.
What's wrong? Which is the correct way to make a page refresh after changing language using binded strings?
I did not put a lot of code because I used basically the one provided in the link, but if you need more info I will edit my question.
I finally found a solution to automatically update my application components reacting to language change.
A good tutorial can be found here; briefly you must find a way to notify your app that localized resource is changed.
public class LocalizedStrings : ViewModelBase
{
private static AppResources localizedresources = new AppResources();
public AppResources LocalizedResources
{
get { return localizedresources; }
}
public void UpdateLanguage()
{
localizedresources = new AppResources();
RaisePropertyChanged(() => LocalizedResources);
}
public static LocalizedStrings LocalizedStringsResource
{
get
{
return Application.Current.Resources["LocalizedStrings"]
as LocalizedStrings;
}
}
}
With this when user change language, you should simply run
LocalizedStrings.LocalizedStringsResource.UpdateLanguage();
and the job is done.

Resources