Xamarin Android: Creating an add user activity, how to display all the error message at once and disabling as and when user fills the form? - xamarin

var nametext = FindViewById<EditText>(Resource.Id.nametext);
var emailtext = FindViewById<EditText>(Resource.Id.emailtext);
Button nextButton = FindViewById<Button>(Resource.Id.next);
nextButton.Click += delegate
{
if (nametext.Text.Length < 1)
{
errorFlag = 0;
nametext.SetError("Please Enter Name", errorIcon);
}
if (emailtext.Text.Length < 1)
{
errorFlag = 0;
emailtext.SetError("Please Enter Email", errorIcon);
}
if (errorFlag == 1)
{
var intent = new Intent(this, typeof(SecondActivity));
intent.PutExtra("name", nametext.Text);
StartActivity(intent);
}
};
After this statement, I can validate one by one but not both at a time on click of submit button. Also should do the regular validation for the email id.

Related

Keeping Data between refreshes in Blazor server

I have a multiple page Web Application that needs to be refreshed after a user has entered in data to then display the data on the table. I have Scoped dependencies so my users do not see the same data table as they are unique to each user. After they enter the data and the page refreshes the page goes blank and the scope is empty. How would I go about keeping the data from the scopes after refresh? I essentially needs a Singlton dependency that isn't shared between users. This is a Blazor Server Side Application. EDIT: Accept Button Method
if (Controlled_Variables.Attendance != null)
{
if (_JBS.CheckFields(_JBF.JobID, _JBF.WorkCenter, _JBF.SetupRun) == false)
{
string prompted = await jsRunTime.InvokeAsync<string>("alert", "Please Verify Job ID, Work Center, and Setup/Run are selected!");
}
else
{
FilledOut = true;
_JBF.transactionData = Guid.NewGuid();
_JBF.jobOperationID = _JBF.WorkCenter;
DateTime recordDate = DateTime.Now;
JobOperationRecord JOR = await _JBS.GetJobOperationRecordByOperationID(_JBF.WorkCenter);
WorkCenterRecord SingleWorkCenter = await _JBS.GetWorkCenterInformation(JOR.Work_Center);
EmployeeRecord Employee = await _JBS.GetEmployeeRecord(Controlled_Variables.Employee_ID);
try
{
if (Check.IsThisAnActiveJob(_JBF.JobID))
{
bool Complete = await First_Article_Complete(_JBF.jobOperationID, _JBF.SetupRun);
if (Complete)
{
Controlled_Variables.Sessions.Clear();
Controlled_Variables.Sessions = await _JBS.GetOpenJobOperationTimeSessionForUser(Controlled_Variables.Employee_ID);
bool activeNonGhostSession = false;
foreach (JobOperationSessionManager Session in Controlled_Variables.Sessions)
{
if (Session.ghost == "Y")
{
Controlled_Variables.ActiveSession = Session;
activeNonGhostSession = true;
}
}
_JBS.UpdateJobOperationStatus(JOR.Job_Operation.ToString(), JOR.Status == "C" ? "C" : "S");
if (!activeNonGhostSession && !_JBF.GhostedCheck)
{
_JBS.AddNewJobOperationTimeSessionForUser(Controlled_Variables.Employee_ID, "N", _JBF.transactionData.ToString(), JOR.Work_Center,
_JBF.jobOperationID, _JBF.JobID, recordDate.ToString("yyyy-MM-dd HH:mm:ss"), _JBF.jobOperationTime.ToString(), _JBF.SetupRun);
_JBF.sessionManagerCreated = true;
_JBS.InsertIntoTransactionDetail_NewEntry_JobOperation(_JBF.transactionData.ToString(), _JBF.jobOperationID, _JBF.jobOperationTime.ToString(),
JOR.Work_Center, _JBF.JobID);
_JBF.transDetailCreated = true;
_JBS.InsertIntoTransactionData_NewEntry_JobOperation(_JBF.transactionData.ToString(), Controlled_Variables.Employee_ID, recordDate.ToString());
_JBF.transDataCreated = true;
_JBS.InsertIntoJobOperationTime_NewEntry_JobOperationStart(_JBF.jobOperationID, Controlled_Variables.Employee_ID, recordDate.ToString(),
Employee.Hourly_Rate.ToString(), SingleWorkCenter.Labor_Burden.ToString(), SingleWorkCenter.Machine_Burden.ToString(), SingleWorkCenter.GA_Burden.ToString(),
_JBF.jobOperationTime.ToString(), JOR.Work_Center, _JBF.jobOperationTimeObjectID.ToString(), JOR.ObjectID.ToString(), Employee.ObjectID.ToString());
_JBF.jobOperationTimeCreated = true;
btnStartJob = true;
btnStopJob = false;
NavManage.NavigateTo(NavManage.Uri, forceLoad: true);
string prompted = await jsRunTime.InvokeAsync<string>("alert", "The job has been entered successfully.", "ERROR");
Sorry for the confusion for the use of refresh. I needed to reload the table to allow the data put in by users to be visable after they hit accept. To do this I added a navigation manager
NavManage.NavigateTo(NavManage.Uri, forceLoad: true);
Which force loads the page and displays the new data. If there may be another way to do this to keep the scope I am open to using a different method. As you can see I have tried to just recall the method in which the table data is loaded into to possibly get the new data populated but then the application never reiterates the loop to actually display the data on the page
#for (int i = 0; i < Controlled_Variables.TransactionData.Count; i++)
{
var TransacData = Controlled_Variables.TransactionData[i];
TransacData.index = i;
#for (int l = 0; l < Controlled_Variables.TransactionDetail.Count; l++)
{
var transacdetail = Controlled_Variables.TransactionDetail[l];
transacdetail.index = l;
TransactionDetailRecord selectData = Controlled_Variables.TransactionDetail[l];
#if (transacdetail.Transaction_Data == TransacData.Transaction_Data)
{
<div><input value="#selectData" type="radio" name="Select" onclick="#(() => ShowSelectedRecord(selectData, TransacData))"> </div>
<div>#transacdetail.Target_Integer</div>
<div>#transacdetail.Job</div>
<div>#Controlled_Variables.Job.Part_Number</div>
<div>#TransacData.Transaction_Start</div>
if (TransacData.Transaction_Type == 10)
{
<div>#TransacData.Transaction_Type</div>
btnStartJob = true;
btnStopJob = false;
}
else
{
<div>#TransacData.Transaction_Type</div>
btnStartJob = false;
btnStopJob = true;
}
<div>#Controlled_Variables.Job.Customer</div>
<div>#transacdetail.Work_Center</div>
<div>#transacdetail.Quantity</div>
<div>#TransacData.Transaction_End</div>
<div>#transacdetail.Entry_Type</div>
<div>#transacdetail.Labor_Hrs</div>
<div>#transacdetail.Machine_Hrs</div>
<div>#TransacData.Transaction_Data</div>
<div>#transacdetail.Transaction_Detail</div>
}
}
}

Adding a swipe to next gesture using Syncfusion.SfChart

Currently on my app when the user selects their 'symptom' they are directed to the detail page which shows their symptom chart with the populated feedback data from their selected symptom.
Is their a way i can add a swipe gesture to allow the user to swipe to the next symptom chart without having to go back to main symptoms page and selecting a symptom.
Currently this is how i populate my chart :
public async Task GetSymptomFeedback(string id)
{
SymptomFeedbackData.Clear();
symptomChart.Series.Clear();
BusyIndicator.IsRunning = true;
SymptomFeedbackData = await symptomsfeedbackmanager.getUserSymptomFeedback(id);
foreach (var FeedbackItem in SymptomFeedbackData)
{
FeedbackItem.Idusersymptomid = FeedbackItem.Id + ',' + FeedbackItem.Usersymptomid;
}
IEnumerable<SymptomFeedback> OrdreredFeedbackData = SymptomFeedbackData.OrderBy(X => X.DateTime);
LineSeries columnseries = new LineSeries
{
ItemsSource = OrdreredFeedbackData,
XBindingPath = "DateTime",
YBindingPath = "Intensity",
DataMarker = new ChartDataMarker
{
ShowLabel = true,
ShowMarker = true,
MarkerHeight = 5,
MarkerWidth = 5,
MarkerColor = Xamarin.Forms.Color.Purple
}
};
BusyIndicator.IsRunning = false;
symptomChart.PrimaryAxis.ShowTrackballInfo = true;
if (columnseries.ItemsSource != null)
{
symptomChart.Series.Add(columnseries);
}
symptomChart.ChartBehaviors.Add(new ChartTrackballBehavior());
//Sort Collection by datetime
SymptomsList.ItemsSource = OrdreredFeedbackData.Reverse();
}
Solution:
Through your code, we can see you query the data through the id of symptom. So, I guess you pass this id as parameter when you go to the detail page from main symptoms page.
Is their a way i can add a swipe gesture to allow the user to swipe to
the next symptom chart without having to go back to main symptoms page
and selecting a symptom.
In additional, you can pass a array of id of all symptoms to detail page. Let's name this array as symptomIdArray.
Then add a SwipeGestureRecognizer to your view.
var DownSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Down };
var UpSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Up };
DownSwipeGesture.Swiped += OnSwiped;
UpSwipeGesture.Swiped += OnSwiped;
this.Content.GestureRecognizers.Add(DownSwipeGesture);
this.Content.GestureRecognizers.Add(UpSwipeGesture);
In the OnSwiped, you can get last or next id through the symptomIdArray and currentID , and then you can choose to reload your current page or go to a new page to swipe to the next symptom chart, here is code:
public Array symptomIdArray; // ids of all symptom
public string currentID; // You selected id of current symptom
void OnSwiped(object sender, SwipedEventArgs e)
{
int index = Array.IndexOf(symptomIdArray, currentID);
switch (e.Direction)
{
case SwipeDirection.Up:
if (index ==0)
{
//first one
break;
}
string lastID = (string)symptomIdArray.GetValue(index-1);
//1.You can refresh current page with lastId
GetSymptomFeedback(lastID);
//2.You can go to a new page with lastID ID and symptomIdArray
Navigation.PushAsync(new NewPage(lastID, symptomIdArray));
break;
case SwipeDirection.Down:
// Handle the swipe
if (index == symptomIdArray.Length-1)
{
//Last one, no more
break;
}
string nextID = (string)symptomIdArray.GetValue(index+1);
//1.You can refresh current page with next currentID
GetSymptomFeedback(nextID);
//2.You can go to a new page with nextID ID and symptomIdArray
Navigation.PushAsync(new NewPage(nextID, symptomIdArray));
break;
}
}
Update:
Add SwipeGestureRecognizer:
SfChart chart = new SfChart();
chart.Title.Text = "Chart";
//Config chart....
...
chart.Series.Add(series);
this.Content = chart;
var DownSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Down };
var UpSwipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Up };
DownSwipeGesture.Swiped += OnSwiped;
UpSwipeGesture.Swiped += OnSwiped;
chart.GestureRecognizers.Add(DownSwipeGesture);
chart.GestureRecognizers.Add(UpSwipeGesture);
And onSwipe:
void OnSwiped(object sender, SwipedEventArgs e)
{
switch (e.Direction)
{
case SwipeDirection.Up:
Console.WriteLine("up");
break;
case SwipeDirection.Down:
Console.WriteLine("down");
break;
}
}
Let me know if you have any question.

Validation for textbox with two sets of phone numbers

I am trying to do a validation on a textbox that can allow the input of one or more phone number in a single textbox. What I am trying to do is to send an message to the phone numbers included in the textbox.
I have no problem when I enter just one set of number into the textbox and the message can be sent.
However, whenever I type two sets of digit into the same textbox, my validation error will appear.
I am using user controls and putting the user control in a listview.
Here are my codes:
private ObservableCollection<IFormControl> formFields;
internal ObservableCollection<IFormControl> FormFields
{
get
{
if (formFields == null)
{
formFields = new ObservableCollection<IFormControl>(new List<IFormControl>()
{
new TextFieldInputControlViewModel(){ColumnWidth = new GridLength(350) ,HeaderName = "Recipient's mobile number *" , IsMandatory = true, MatchingPattern = #"^[\+]?[1-9]{1,3}\s?[0-9]{6,11}$", Tag="phone", ContentHeight = 45, ErrorMessage = "Please enter recipient mobile number. "},
});
}
return formFields;
}
}
And here is the codes for the button click event:
private void OkButton_Click(object sender, RoutedEventArgs e)
{
MessageDialog clickMessage;
UICommand YesBtn;
int result = 0;
//Fetch Phone number
var phoneno = FormFields.FirstOrDefault(x => x.Tag?.ToLower() == "phone").ContentToStore;
string s = phoneno;
string[] numbers = s.Split(';');
foreach (string number in numbers)
{
int parsedValue;
if (int.TryParse(number, out parsedValue) && number.Length.Equals(8))
{
result++;
}
else
{ }
}
if (result.Equals(numbers.Count()))
{
try
{
for (int i = 0; i < numbers.Count(); i++)
{
Class.SMS sms = new Class.SMS();
sms.sendSMS(numbers[i], #"Hi, this is a message from Nanyang Polytechnic School of IT. The meeting venue is located at Block L." + Environment.NewLine + "Click below to view the map " + Environment.NewLine + location);
clickMessage = new MessageDialog("The SMS has been sent to the recipient.");
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
YesBtn = new UICommand("Ok", delegate (IUICommand command)
{
timer.Stop();
idleTimer.Stop();
var rootFrame = (Window.Current.Content as Frame);
rootFrame.Navigate(typeof(HomePage));
rootFrame.BackStack.Clear();
});
clickMessage.Commands.Add(YesBtn);
clickMessage.ShowAsync();
}
}
catch (Exception ex)
{ }
}
}
I am trying to separate the two numbers with ";" sign.... and I am wondering if that is the problem. Or maybe it is the matchingpattern that I have placed in.
The answer is quite simple, create a bool property in your TextFieldInputControlViewModel something like
public bool AcceptMultiple {get;set;}
and to keep things dynamic, create a char property as a separator like below:
public char Separator {get;set;}
Now, modify your new TextFieldInputControlViewModel() code statement by adding values to your new fields like below:
new TextFieldInputControlViewModel(){Separator = ';', AcceptMultiple = true, ColumnWidth = new GridLength(350) ,HeaderName = "Recipient's mobile number *" , IsMandatory = true, MatchingPattern = #"^[\+]?[1-9]{1,3}\s?[0-9]{6,11}$", Tag="phone", ContentHeight = 45, ErrorMessage = "Please enter recipient mobile number. "},
Once it's done, now in your checkValidation() function (or where you check the validation or pattern match) can be replaced with something like below:
if(AcceptMultiple)
{
if(Separator == null)
throw new ArgumentNullException("You have to provide a separator to accept multiple entries.");
string[] textItems = textField.Split(Separator);
if(textItems?.Length < 1)
{
ErrorMessage = "Please enter recipient mobile number." //assuming that this is your field for what message has to be shown.
IsError = true; //assuming this is your bool field that shows all the errors
return;
}
//do a quick check if the pattern matching is mandatory. if it's not, just return.
if(!IsMandatory)
return;
//your Matching Regex Pattern
Regex rgx = new Regex(MatchingPattern);
//loop through every item in the array to find the first entry that's invalid
foreach(var item in textItems)
{
//only check for an invalid input as the valid one's won't trigger any thing.
if(!rgx.IsMatch(item))
{
ErrorMessage = $"{item} is an invalid input";
IsError = true;
break; //this statement will prevent the loop from continuing.
}
}
}
And that'll do it.
I've taken a few variable names as an assumption as the information was missing in the question. I've mentioned it in the comments about them. Make sure you replace them.

gridpanel ext.net communication failure error firefox

I have a ext:gridpanel in my application and we have given the user the ability to arrange columns as per his convenience in the grid.
We also have given a button reset columns to default so that user can go back to the original gridpanel column order.
A method is written in javascript file to bring back the grid to original state when the user clicks "Reset Column to Default button"
The click handler for this button calls the method-"gridpanel_restore"
The code for this method is:-
var gridpanel_restore = function (grid) {
try
{
grid._State = appGlobal.getGridState(grid);
if (grid._State == grid._DefaultState) {
return;
}
grid._State = grid._DefaultState;
var settings = Ext.decode(grid._State);
var cm = grid.getColumnModel();
if (cm.isLocked != null) {
for (var i = cm.columns.length - 1; i > 0; i--) {
if (cm.isLocked(i) && !settings.settings[0].lockField.contains(i)) {
cm.setLocked(i, false, false);
}
}
for (var j = 0; j < settings.settings[0].lockField.length; j++) {
if (!cm.isLocked(i)) cm.setLocked(settings.settings[0].lockField[j], true, false);
}
}
if (settings.settings[0].state.sort) {
}
else {
grid.store.sortInfo = null;
}
grid.applyState(settings.settings[0].state);
var lastColumn = cm.getColumnAt(cm.columns.length - 1);
cm.setColumnWidth(cm.columns.length - 1, lastColumn.width - 1, false);
noMask = true;
CMS.ResetUserSettings(grid._ControlID);
if (settings.settings[0].state.group != null) {
async: false
window.location.href = window.location.href;
}
}
catch (err) {
}
}
This code works perfectly fine in IE but in firefox I get Communication failure on line "window.location.href = window.location.href;" on line 34
I have used this line because the page should be reloaded after setting columns to default otherwsise the grid does not render properly.
I have seen posts related to this but could not find a solution.
Please help. I have already asked this question in ext.net forum but no answer.

How to replace or destroy a tab using the Firefox Add-on SDK?

I did not find anything in the Firefox Add-on SDK (Tab API) that can destroy a tab or replace it with a new tab. I can find the Tab ID, Tab URL, or other identifier. Is there any way to replace or destroy a tab?
Use tab.close(callback).
What do you mean by replace? If you just want to change the URL, then use tab.url = url.
I don't know about SDK, but you can destroy and replace one tab with another tab.
This is how to do it with non-sdk:
How to close a tab by its "id"
var tabIdToClose = 'panel-3-1';
Cu.import('resource://gre/modules/Services.jsm');
var DOMWindows = Services.wm.getEnumerator('navigator:browser');
while (DOMWindows.hasMoreElements()) {
var aDOMWindow = DOMWindows.getNext();
if (aDOMWindow.gBrowser && aDOMWindow.gBrowser.tabContainer) {
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
var aTab = tabs[i];
var aTabId = aTab.getAttribute('linkedpanel');
console.log('tab id:', aTabId);
if (aTabId == tabIdToClose) {
aDOMWindow.gBrowser.removeTab(aTab);
}
}
} else {
//this window does not have any tabs
}
}
This is how to replace tab with another tab and close the first tab.
var tabIdToReplace = 'panel-3-248';
var tabIdToReplaceWith = 'panel-3-246'; //this tab will be closed, but its contents will be in tabIdToReplace
var aTabToReplace;
var aTabToReplaceWith;
Cu.import('resource://gre/modules/Services.jsm');
var DOMWindows = Services.wm.getEnumerator('navigator:browser');
while (DOMWindows.hasMoreElements()) {
var aDOMWindow = DOMWindows.getNext();
if (aDOMWindow.gBrowser && aDOMWindow.gBrowser.tabContainer) {
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
var aTab = tabs[i];
var aTabId = aTab.getAttribute('linkedpanel');
console.log('tab id:', aTabId);
if (aTabId == tabIdToReplace) {
aTabToReplace = aTab;
} else if (aTabId == tabIdToReplaceWith) {
aTabToReplaceWith = aTab;
}
if (aTabToReplace && aTabToReplaceWith) {
aTabToReplaceWith.ownerDocument.defaultView.gBrowser.swapBrowsersAndCloseOther(aTabToReplace, aTabToReplaceWith);
break;
}
}
} else {
//this window does not have any tabs
}
}
If you just want to swap the tabs without closing either then do this
I havent completed this so the swap isn't perfect, like I have to set the iconURL and title of the tab that would have been closed: https://gist.github.com/Noitidart/9b335a460f53b0390336

Resources