Databinding Entry in Xamarin Forms - xamarin

I'm trying to capture the value of the entry in a Login text box in Xamarin Forms. I've created the class, data bound in xmal, but running into build errors when compiling for iOS. Any pointers much appreciated.
Login.xmal:
<Entry x:Name="{Binding Source = AppLoginUsername;}" Placeholder="Username"
Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3"
HorizontalOptions="StartAndExpand" WidthRequest="300" />
FormEntry Class.cs
using System;
namespace SGC.Class
{
public class FormEntryBindings
{
public FormEntryBindings()
{
}
public static string AppLoginUserName { get; set; }
}
}
Home.cs (Grabs the username entered in Login page and figures out the CustomerID)
private async void getCustBalance()
{
HttpClient client = new HttpClient();
string x = FormEntryBindings.AppLoginUserName;
int custid = GetCustomerId(x);
The errors are:
Invalid token '{' in class, struct, or interface member declaration
Invalid expression term '='
Type or namespace definition, or end-of-file expected

Why dont you just give it a name, and bind the text?
Eg
x:Name=“User” Text=“{Binding AppLoginUsername}”...

Well, based on the comments, I think your problem is that you can get the AppLoginUserName in the login page, however,you want use the AppLoginUserName in another page(another view).
I would give your several suggestions:
1.You can pass the value to the page where you want to use.
2.Use Xamarin.Essentials: Preferences.
You can save the AppLoginUserName once the user has logged in:
using Xamarin.Essentials;
Preferences.Set("AppLoginUserName", "value");
At another view where you want to use, you can get the value:
var myValue = Preferences.Get("AppLoginUserName", "default_value");
And remove the key from preferences when the user has logged out or under other situation:
Preferences.Remove("my_key");
You can refer:essentials/preferences

You can’t bind the name. Name is something that generates the code and you can’t change the name of the variable on the fly.

Related

Catch API result - Xamarin Forms

i have this function in my shared project which i referenced to my new project. basically this function job is to fetch contact information from my api.
GetContact() function
i call it when i load my profile page and set the result object (contact) as my profile page bindingcontext.
calling the function
which i binded on my ui.
ui
my problem is, since fetching data on api is always async. my code execute and exit immediately even the result from api is not yet fetch. resulting into a null bindingcontext. is there any way that i can catch the api result and update my bindingcontext so that my be updated ui also?
For the async BindingContext I use the following:
XAML:
<Label Text="{Binding Type}"
TextColor="#142E5F"
Margin="10,0,0,0"
Font="Bold, 15"/>
ViewModel:
public int _type;
public int Type
{
get => _type;
set => SetProperty(ref _type, value);
}
With the SetProperty, you can change the value in execution time. You just need to asign the result.
public override async void OnAppering()
{
base.OnAppering();
Type = await APICall();
}

Mvvmcross: Text format binding with MvxLang

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

Using PathIcon from resources results in XamlParseException

Universal Store Project for 8.1 here.
I have a PathIcon declared in a ResourceDictionary like this:
<PathIcon
x:Key="PhoneIcon"
Data="F0 M22,22z M0,0z M17.4,22.533333C19.111111,25.955556,22.044444,28.766667,25.466667,30.6L28.155556,27.911111C28.522222,27.544444 29.011111,27.422222 29.377778,27.666667 30.722222,28.155556 32.188889,28.4 33.777778,28.4 34.511111,28.4 35,28.888889 35,29.622222L35,33.777778C35,34.511111 34.511111,35 33.777778,35 22.288889,35 13,25.711111 13,14.222222 13,13.488889 13.488889,13 14.222222,13L18.5,13C19.233333,13 19.722222,13.488889 19.722222,14.222222 19.722222,15.688889 19.966667,17.155556 20.455556,18.622222 20.577778,18.988889 20.455556,19.477778 20.211111,19.844444L17.4,22.533333 17.4,22.533333z"
/>
I can get this resource in code behind like this:
PathIcon icon1 = null;
object resource;
if (Application.Current.Resources.TryGetValue("PhoneIcon", out resource)) {
icon1 = resource as PathIcon;
};
Alternatively, I can create it like this (avoiding querying resource dictionary):
var icon2 = XamlReader.Load(
#"<PathIcon
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
Data=""F0 M22,22z M0,0z M17.4,22.533333C19.111111,25.955556,22.044444,28.766667,25.466667,30.6L28.155556,27.911111C28.522222,27.544444 29.011111,27.422222 29.377778,27.666667 30.722222,28.155556 32.188889,28.4 33.777778,28.4 34.511111,28.4 35,28.888889 35,29.622222L35,33.777778C35,34.511111 34.511111,35 33.777778,35 22.288889,35 13,25.711111 13,14.222222 13,13.488889 13.488889,13 14.222222,13L18.5,13C19.233333,13 19.722222,13.488889 19.722222,14.222222 19.722222,15.688889 19.966667,17.155556 20.455556,18.622222 20.577778,18.988889 20.455556,19.477778 20.211111,19.844444L17.4,22.533333 17.4,22.533333z""
/>"
) as PathIcon;
Both ways get me a PathIcon instance that looks just fine (icon1 and icon2 seem to be identical).
Debug.WriteLine(
"{0} equals {1}: {2}",
icon1.Data.Bounds, icon2.Data.Bounds,
icon1.Data.Bounds.Equals(icon2.Data.Bounds)
); // outputs 13,13,22,22 equals 13,13,22,22: True
I'm trying to use the icon for an AppBarButton:
SomeCommandBar.PrimaryCommands.Add(new AppBarButton(){
Label = "Label",
Icon = icon1 or icon2,
Command = SomeCommand
});
The problem is: when I use icon2 (created with XamlReader), everything works just fine, but when I use icon1 (fetched from resourcedictionary), I get a XamlParseException:
"Failed to assign to property '%0'. [Line: 0 Position: 0]"
I'd appreciate any ideas as to why this may be happening.
UPDATE
This doesn't work either (the error is the same as above):
<Page.BottomAppBar>
<CommandBar>
<AppBarButton
Label="Test"
Icon="{StaticResource PhoneIcon}"
/>
</CommandBar>
</Page.BottomAppBar>
So, I guess, there's no way this can work at all. It simply doesn't work with static resource in this place. Guess I'll have to store string resources with icons and XmlReader.Load() them every time, as Chris W. suggested in the comments.
HOWEVER
The following does work for some reason (not that it's useful in any way):
PathIcon icon1 = null;
object resource;
if (Application.Current.Resources.TryGetValue("PhoneIcon", out resource)) {
icon1 = resource as PathIcon;
// if the resource is removed from the dictionary before it is used,
// no exception is thrown.
foreach(var m in Application.Current.Resources.MergedDictionaries) {
if (m.ContainsKey("PhoneIcon")) {
m.Remove("PhoneIcon"); // This does it
}
}
};
I find that the data path is far more complex in the declarative XAML of resources than the implicit converter of the Data property. Since you have it working as a Data property, let Visual Studio do the work. Open the properties dialog in the XAML designer and click the small right square (it will be black at first) net to the Data property and select "Make Resource". The resulting wizard will guide you, and you will see the data string is converted into its component parts and will work with way you want it to after you do this.
Best of luck.

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