Change display language within an xamarin Android app - xamarin.android

How can I change the display language within an app? I want that users with different cultures can work with one scanner without changing the global culture of the device.
I have a language button with a click event in which I call a method:
public void SetLocale(string language = "")
{
Locale locale = String.IsNullOrEmpty(language)
? new Locale("de-DE")
: new Locale(language);
Locale.Default = locale;
var config = new global::Android.Content.Res.Configuration();
config.Locale = locale;
var context = global::Android.App.Application.Context;
context.Resources.UpdateConfiguration(config, context.Resources.DisplayMetrics);
}
But unfortunately nothing happens when I press the button.
The click event is:
_btnen.Click += delegate
{
SetLocale("en-GB");
};

What can work for You, if the context can be forgotten (all property values can be lost), You can just force the Activity to redraw itself.
btn.Click += delegate
{
SetLocale("en-GB");
this.Recreate(); //this line
}

With help of #Rafael Stahl, I found following solution:
_btnen.Click += delegate
{
Java.Util.Locale.Default = new Locale("en", "GB");
Resources.Configuration.Locale = Java.Util.Locale.Default;
Resources.UpdateConfiguration(Resources.Configuration, Resources.DisplayMetrics);
Intent intent = new Intent(this, this.Class);
StartActivity(intent);
};

Based on the answers of user1230268 and Tatranskymedved:
_btnen.Click += delegate
{
Java.Util.Locale.Default = new Locale("en", "GB");
Resources.Configuration.Locale = Java.Util.Locale.Default;
Resources.UpdateConfiguration(Resources.Configuration, Resources.DisplayMetrics);
// Redraw
this.Recreate();
};

Related

Xamarin crash file # xamarin_get_block_descriptor

I am new to iOS Crash debugging but I managed to find the crash file and and symbolicate it (I think? I pressed the button in any case). Here is the thread that crashed info. It occurs occasionally on the load of one specific view:
The view initializes the view model and starts a timer:
InitializeComponent();
var vm = new OpenBatchesViewModel();
this.BindingContext = vm;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>{ some code here})
and the view model calls out to an API for some data:
public OpenBatchesViewModel()
{
SearchString = string.Empty;
CutOff = RemitStationApiService.GetCutOffTime().Result;
Username = RemitStationApiService.GetUsername();
_openBatches = RemitStationApiService.GetOpenBatches().Result.ToList();
CurrentBatchList = new ItemObservableCollection<OpenBatch>(_openBatches);
CurrentBatchList.ItemPropertyChanged += _currentBatchList_ItemPropertyChanged;
OpenContextMenuCommand = new Command<OpenBatch>(batch => BatchButtonClick(batch));
Activity = false;
}
The view model implements INotifyPropertyChanged.
TIA
Check out Microsoft AppCenter's diagnostic abilities to track crashes.

Warning: View is not in Window Hierarchy in Xamarin.Forms

I am doing a Xamarin project, Forms and I have integrated Xam.Plugins.Messaging to send SMS from my app. For this I have created a custom renderer in my iOS project with below code:
AppDelegate smsObj = new AppDelegate();
bool a= smsObj.ShowAndSendSMS(new string[] { "123" }, "Hi there");
And in my AppDelegate, I have the code as below:
public bool ShowAndSendSMS(string[] recipients, string body)
{
UIViewController sms = new UIViewController();
if (MFMessageComposeViewController.CanSendText)
{
MFMessageComposeViewController message = new MFMessageComposeViewController();
message.Finished += (sender, e) => {
message.DismissViewController(true, null);
};
message.Body = body;
message.Recipients = recipients;
sms.PresentModalViewController(message, false);
}
return true;
}
The problem I am facing is on my first-time app launch, the functionality to share SMS doesn't work and the debug log gives me warning like "Attempt to present on whose view is not in the window hierarchy!"
However, if I restart the app, the same functionality works like a charm. Any ideas from where i have made mistake?
I think the problem is with the fact that you're newing up an AppDelegate and calling the ShowAndSendSMS from there. iOS is going to new up that AppDelegate for you upon app startup, and you should always use that, as opposed to creating a new instance of AppDelegate (at least I've never seen a situation that called for a multi-AppDelegate-instance pattern). So, try this:
Create a helper class in your project like this (I don't really like the word "helper", but that's beside the point; name it something fitting for your project):
using Foundation;
using UIKit;
public class SmsHelper
{
public bool ShowAndSendSMS(string[] recipients, string body)
{
if (MFMessageComposeViewController.CanSendText)
{
UIViewController sms = new UIViewController();
MFMessageComposeViewController message = new MFMessageComposeViewController();
message.Finished += (sender, e) => {
message.DismissViewController(true, null);
};
message.Body = body;
message.Recipients = recipients;
sms.PresentModalViewController(message, false);
}
return true;
}
}
And then change your page renderer to consume it like this:
public class SMS_Ios: PageRenderer
{
private readonly TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
SmsHelper smsObj = new SmsHelper();
bool a = smsObj.ShowAndSendSMS(new string[] {"123"}, "Hi there");
}
}
And finally, remove ShowAndSendSMS from your AppDelegate.cs, since you'll be using your SMS helper going forward.
Let me know if that works for you.
If you have already installed the Xam.Plugins.Messaging package in the PCL and your platforms. You can just use the API from it in PCL to implement that without any special codes in your iOS platform.
You can just use the APIs of Xam.Plugins.Messaging in the PCL, like this:
// Send Sms
var smsMessenger = CrossMessaging.Current.SmsMessenger;
if (smsMessenger.CanSendSms)
smsMessenger.SendSms("+27213894839493", "Well hello there from Xam.Messaging.Plugin");
Reference: Messaging Plugin for Xamarin and Windows.

Update autoComplete JavaFx?

I'm currently working on a JavaFX project.I'm using Autcomplete TextField of ControlFx .Each time i add new rows in database table, it should to update Autocomplete ,i did this but my problem is showing double Context-Menu ,we can say double autocompletes because i call method that create autocomplete each adding of new elements in table.
When i click a tab editBill i call this method :
public void showEditBill() {
if (!BillPane.getTabs().contains(EditBillTab)) {
BillPane.getTabs().add(EditBillTab);
}
SingleSelectionModel<Tab> selectionModel = BillPane.getSelectionModel();
selectionModel.select(EditBillTab);
/*it should remove the old autocomplete from textfield*/
pushBills(); //Call for cheking new items
}
pushBills method () :
public void pushBills() {
ArrayList list = new ArrayList<>();
bills = new BillHeaderDao().FindAll();
for (int i = 0; i < bills.size(); i++) {
list.add(bills.get(i).getIdClient());
}
//How can i remove the old bind before bind again
autoCompletionBinding = TextFields.bindAutoCompletion(SearchBill, SuggestionProvider.create(list));
}
How i can remove the old autocomplete and bind new automplete?
Just in any case if you need to keep instance of AutoCompletionTextFieldBinding object, thus avoiding use of:
autoCompleteBinding = TextFields.bindingAutoCompletion(TextField,List);
, which will change the instance, we could go a little bit deeper and use this:
// let's suppose initially we have this possible values:
Set<String> autoCompletions = new HashSet<>(Arrays.asList("A", "B", "C"));
SuggestionProvider<String> provider = SuggestionProvider.create(autoCompletions);
new AutoCompletionTextFieldBinding<>(textField, provider);
// and after some times, possible autoCompletions values has changed and now we have:
Set<String> filteredAutoCompletions = new HashSet<>(Arrays.asList("A", "B"));
provider.clearSuggestions();
provider.addPossibleSuggestions(filteredAutoCompletions);
So, through SuggestionProvider, we have "updated" auto completion values.
To avoid doubling of suggestions menu, don't use again (for the 2nd time):
TextFields.bindAutoCompletion(..)
In order to provide updates to the auto-complete suggestion list, retain a reference to the SuggestionProvider and update the suggestion provider instead:
TextField textField = new TextField();
SuggestionProvider suggestionProvider = SuggestionProvider.create(new ArrayList());
new AutoCompletionTextFieldBinding<>(textField, suggestionProvider);
When you want to update the suggestion list:
List<String> newSuggestions = new ArrayList();
//(add entries to list)
suggestionProvider.clearSuggestions();
suggestionProvider.addPossibleSuggestions(newSuggestions);
This will do the trick:
Instead of: TextFields.bindAutoCompletion(textField, list);
, try this:
List<String> strings = new ArrayList<>();
Then create binding between your textField with the list through:
new AutoCompletionTextFieldBinding<>(textField, SuggestionProvider.create(strings));
So any changes, including removing, from the list, will be reflected in the autoCompletion of the textField;
And you will have dynamic filtering of suggestions, showed in pop-up, when user enter some text in textField;
I had the same problem some time ago I try to do as #MaxKing mentions, but it didnt work. I managed to give it a soluciĆ³n even though I don't think it's the right way.
// Dispose the old binding and recreate a new binding
autoCompleteBinding.dispose();
autoCompleteBinding = TextFields.bindingAutoCompletion(TextField,List);
try this:
public void pushBills() {
ArrayList list = new ArrayList<>();
bills = new BillHeaderDao().FindAll();
for (int i = 0; i < bills.size(); i++) {
list.add(bills.get(i).getIdClient());
}
autoCompletionBinding.dispose();
autoCompletionBinding = TextFields.bindAutoCompletion(SearchBill, SuggestionProvider.create(list));
}

Listing WorkItem State Reasons programmatically

We have a customised TFS workflow, I want to be able to access the Reasons I can close a Bug (change the state from Active to Closed) from TFS so that we don't have to update our code every time we want to tweak our process.
This is what I have so far:
WorkItemType wiType = this.GetWorkItemStore().Projects[this.ProjectName].WorkItemTypes["Bug"];
var reason = wiType.FieldDefinitions["Reason"];
var state = wiType.FieldDefinitions["State"];
var filterList = new FieldFilterList();
FieldFilter filter = new FieldFilter(wiType.FieldDefinitions[CoreField.State], "Active");
filterList.Add(filter);
var allowedReasons = reason.FilteredAllowedValues(filterList);
However I'm not getting any results. I'd like to get a list of all the reasons why I can close a bug (Not Reproduceable, Fixed etc)
There isn't any easy way to get the transition via API directly as I know since the API read the allowed values from database directly.
The alternative way would be export the workitemtype definition via WorkItemType.Export() method and then get the information from it. Vaccano's answer in this question provided the entire code sample you can use.
Edited to give an example of how I solved this using the above recommendation:
public static List<Transition> GetTransistions(this WorkItemType workItemType)
{
List<Transition> currentTransistions;
// See if this WorkItemType has already had it's transistions figured out.
_allTransistions.TryGetValue(workItemType, out currentTransistions);
if (currentTransistions != null)
return currentTransistions;
// Get this worktype type as xml
XmlDocument workItemTypeXml = workItemType.Export(false);
// Create a dictionary to allow us to look up the "to" state using a "from" state.
var newTransistions = new List<Transition>();
// get the transistions node.
XmlNodeList transitionsList = workItemTypeXml.GetElementsByTagName("TRANSITIONS");
// As there is only one transistions item we can just get the first
XmlNode transitions = transitionsList[0];
// Iterate all the transitions
foreach (XmlNode transition in transitions)
{
XmlElement defaultReasonNode = transition["REASONS"]["DEFAULTREASON"];
var defaultReason = defaultReasonNode.Attributes["value"].Value;
var otherReasons = new List<string>();
XmlNodeList otherReasonsNodes = transition["REASONS"].SelectNodes("REASON");
foreach (XmlNode reasonNode in otherReasonsNodes)
{
var reason = reasonNode.Attributes["value"].Value;
otherReasons.Add(reason);
}
// save off the transistion
newTransistions.Add(new Transition
{
From = transition.Attributes["from"].Value,
To = transition.Attributes["to"].Value,
DefaultReason = defaultReason,
OtherReasons = otherReasons
});
}
// Save off this transition so we don't do it again if it is needed.
_allTransistions.Add(workItemType, newTransistions);
return newTransistions;
}

DevExpress MVC PivotGrid Custom Actions Keep Firing

I am using a DevExpress MVC Pivot Grid and trying to work out some problems with the loading and saving of layouts. So far I have the following:
I have set my CustomActionRouteValues in the PivotGridSettings as follows:
CustomActionRouteValues = new { Controller = "Home", Action = "PivotGridCustomCallback" },
Which points to the following:
public ActionResult PivotGridCustomCallback(string action, string reportName)
{
if (string.IsNullOrEmpty(reportName))
{
reportName = "Report 1";
}
var settings = PivotGridLayoutHelper.DefaultPivotGridSettings;
if (action == "Save")
{
// TODO: Find a better solution than this. At the moment, if Save is called once, it is then called again every time the user changes the layout.. which is why we have the 'saved' variable here.
bool saved = false;
settings.AfterPerformCallback = (sender, e) =>
{
if (saved)
{
return;
}
SaveLayout(((MVCxPivotGrid)sender).SaveLayoutToString(), reportName);
saved = true;
};
}
else if (action == "Load")
{
// TODO: Find a better solution than this. At the moment, if Load is called once, it is then called again every time the user changes the layout.. which is why we have the 'loaded' variable here.
bool loaded = false;
string layoutString = LoadLayout(reportName);
if (!string.IsNullOrEmpty(layoutString))
{
settings.BeforeGetCallbackResult = (sender, e) =>
{
if (loaded)
{
return;
}
((MVCxPivotGrid)sender).LoadLayoutFromString(layoutString, PivotGridWebOptionsLayout.DefaultLayout);
loaded = true;
};
}
}
ViewBag.PivotSettings = settings;
return PartialView("PivotPartial");
}
The problem, as you can see in the code comments, is that after performing an action just one time, it then gets called EVERY time I make any sort of change. So, for example... say I load a report.. that's fine.. but then when I try expand something or add a field.. or do ANYTHING, nothing seems to happen on the UI.. and I figured out that's because immediately, this code gets called again:
settings.BeforeGetCallbackResult = (sender, e) =>
{
((MVCxPivotGrid)sender).LoadLayoutFromString(layoutString, PivotGridWebOptionsLayout.DefaultLayout);
};
That just keeps resetting the values to the saved layout, which means the UI looks like it's unresponsive when trying to change anything.
This is why I now have the boolean variable called loaded to check if it's already loaded. That works.. but it's an ugly hack.. because it's making unnecessary trips to the server each and every time the user does anything on the pivot grid.
Surely there must be a way to prevent these actions from firing all the time?

Resources