Xamarin Android - Update UI control of one activity from another activity - c#

I have one Fragment "AddNewIncomeFragment " with a TextView("#+id/lblAccountHead"). On click on textview it starts a new activity "AccountHeadListActivit" which shows a list of existing Account Head. On selection of account head from "AccountHeadListActivity" i want to update "lblAccountHead" of first activity with selected account name, other values need to be intact.
Earlier i did it using "messaging center" for xamarin form. Now i trying to do the same in xamarin native(android).
*****UPDATED WITH FIRST SOLUTION APPLIED****
Click event in AddNewIncomeFragment which start account head activity:
public void onAccounyHeadClick(object sender, EventArgs e)
{
var intend = new Intent(this.Activity, typeof(AccountHeadListActivity));
//this.StartActivity(intend);
this.StartActivityForResult(intend, 1000);
}
ListView Selection event of Account head activity
void OnSelection (object sender, SelectedItemChangedEventArgs e)
{
var result = new Intent();
result.PutExtra("name", "Salary Account");
result.PutExtra("id", 2);
SetResult(Result.Ok, result);
Finish();
}
On closing this activity i want to update textview of previous activity with selected account head name/id. Please share what option we have to do this in xamarin andriod, should use StartActivityForResult,Local Notifications or any best approach.
I have implemented above solution and it is working fine. But the issue is- 2nd activity "AccountHeadList" contains an add new account link which start a new activity "AddNewAccount"- Now if user create a new account and save it then this activity need to be closed and 1st activity need to updated with newly created account name. So basically "StartActivityForResult" failed when it involves three activity and need to updated 1st activity from 3rd activity- Please suggest.
Thanks,
#Paul

To receive a result, call
startActivityForResult() instead of startActivity()
then in your second activity, call the setResult(result) method to set the result before you finish the activity finish() after that in your original activity you can override the method
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// set the text view with the data from the result
}

Related

Android OnActivityResult, on second call second activity doesn't return to the first activity after finish

Second activity is called from my First Activity
public static int REQUEST_CODE = 1;
myButton.Click += delegate
{
StartActivityForResult(typeof(SecondActivity), REQUEST_CODE);
};
In the First Activity I override OnActivityResult
protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
{
if (requestCode == 1)
{
if (resultCode == Android.App.Result.Ok)
{
String newdata = data.GetStringExtra("data");
}
}
}
In my second activity I return to the first activity using the following code
Intent returnIntent = new Intent();
returnIntent.PutExtra("data", somedata);
SetResult(Android.App.Result.Ok, returnIntent);
Finish();
This all works well the first go round, I return to the first activity with the correct data. However, the next time the second activity is started, the data is stored correctly, but the activity doesn't finish. It is almost as if the Finish command is ignored and the activity is started again and OnCreate() is invoked. Following that, the next time the above code is invoked it returns to the first activity and two key value pairs are stored in the data. So the data is stored correctly, however the navigation is incorrect. Anyone have any ideas?
Use Intent to start an Activity
StartActivityForResult(new Intent(this, typeof(SecondActivity)), REQUEST_CODE);

Android/C#: Preventing a spinner toast on startup

Problem: I have followed different tutorials on how to implement a spinner in Android, such as this. However, when the app first opens, the toast is made immediately without the user selecting anything.
My Solution: I tried creating a boolean variable, that is it set to 'false' on start-up. The toast will show only once that boolean is set to 'true'. This solution works: no toast is made on start-up, but if the user had to select the first item (which is selected by default), then no toast is made. After the user selects a different option and thereafter re-selects the first option, then only will the toast for the first item be shown. This isn't a major issue though. My code is shown below.
In my OnCreate method, I have the following:
boolToast = false;
Spinner spinner = FindViewById<Spinner>(Resource.Id.spinner);
spinner.SetSelection(0, false);
spinner.ItemSelected += new EventHandler<AdapterView.ItemSelectedEventArgs>(Spinner_ItemSelected);
var adapter = ArrayAdapter.CreateFromResource(this, Resource.Array.array, Android.Resource.Layout.SimpleSpinnerItem);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
spinner.Adapter = adapter;
My spinner_ItemSelected method is as follows:
private void Spinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
{
Spinner spinner = (Spinner)sender;
string toast = string.Format("Selected item is {0}", spinner.GetItemAtPosition(e.Position));
if (boolToast == true)
{
Toast.MakeText(this, toast, ToastLength.Long).Show();
}
boolToast = true;
}
I am satisfied with it already, but wanted to know if there is maybe a more elegant or proper way of achieving this. I have seen a few other fairly similar questions, but those were mostly in Java which I am very unfamiliar with.

how to close activity android using visual studio and xamarin

i have login, register, and home page on my project. I use StartActivity(typeof(Register));to open register page. When user already insert data and click register button, i use StartActivity(typeof(MainActivity)); to go back to login page again.
When i click back button on my phone it back to register page>login page>then exit. I want my activity that already created is closed after i open a new page.
And my second question, i have exit button, how to close my app using the exit button?
I'm using Visual Studio 2015 and Xamarin for developing android app.
Calling Finish will close and kill the Activity and it will work as expected. Better way to remove an Avtivity so that it won't appear when Back button is pressed will be to set the NoHistory of that Activity as true.
If you have a LoginActivity and a DashboardActivity and you don't want the LoginActivity to show while pressing back-button after logging in, you can set NoHistory of LoginActivity as true, like below.
[Activity (NoHistory = true)]
public class LoginActivity : Activity
{
}
You can use Finish method to close your current activity:
StartActivity(typeof(MainActivity));
Finish();
To close the app, simply use
System.exit(0);
To remove an activity from navigation you can use finish keyword like that :
[Activity(Label = "MainActivity", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity: Activity
{
protected override async void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var intent = new Intent(this, typeof(SecondActivity));
intent.SetFlags(ActivityFlags.NewTask);
//Navigation to SecondActivity
StartActivity(intent);
//delete main activity from navigation
Finish();
}
}
For the Second question you can use :
System.exit(0);
You have a very good explanation about this feature in this post for android that you can use for xamarin android :
Close Android Application
StartActivity(typeof(nameOfActivity));
// add this line
Finish();
You can't close previous activity in current activity. It only can be closed by itself.
But you can return data to previous activity. And in event handler OnActivityResult of previous activity, you can do close action.
This sample will be helpful for you. https://code.msdn.microsoft.com/How-to-close-activity-d51941c8
code below shows how to close previous activity.
In previous activity:
Intent intent = new Intent(this, typeof(RegisterActivity));
//for get result, we should use method StartActivityForResult
//the second param is the request code, it is the ID of this request, it should be >= 0
StartActivityForResult(intent, 1);
In current activity:
Intent intent = new Intent(this, typeof(RegisterActivity));
intent.PutExtra("result", "Success");
SetResult(Result.Ok, intent);
Finish();
//when back to login activity, the OnActivityResult event will be trigger.
And go back to previous activity:
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
//when regester activity retrun data, it will be execute
if (requestCode == 1 && resultCode == Result.Ok)
{
string result = data.GetStringExtra("result");
if (result == "Success")
{
Finish();
}
}
}
For your second question:
Just use this:
System.exit(0);

DataBinding() not working with Distinct() (Entity Framework)

I'd like to create an application that reads data from a database and then shows it through a UI. The user then can add/delete/update fields and save it to the DB, pretty standard, right?
I have two tables: Motors and Measures. Motors table has a lot of fields, one of them is "company". Of course, there can be several motors from the same company, so I would like to filter those companies and get only the distinct ones in a comboBox.
I'm still playing around with the language and VS, so I've made a simple version of the UI where the user can add a new motor, in fact, the user can add the company field, because I'm trying to add a new company and see if it updates automatically in the comboBox.
For this purpose, I'm using Entity Framework and this tutorial from msdn for data binding:
https://msdn.microsoft.com/en-us/data/jj682076.aspx
The problem is that when I add a new motor (with a new company), it doesn't update if I filter the distinct ones, I mean, the following code does work and automatically updates the comboBox with all the companies:
private void MainForm_Load(object sender, EventArgs e)
{
_context = new MotorsContext();
_context.Motors.Load();
this.companyBindingSource.DataSource = _context.companies.ToBindingList();
companyBindingSource.ListChanged += CompanyBindingSource_ListChanged;
}
And the following doesn't:
private void MainForm_Load(object sender, EventArgs e)
{
_context = new MotorsContext();
_context.Motors.Load();
this.companyBindingSource.DataSource = _context.Motors.Local.ToBindingList().Select(x => x.company).Distinct();
companyBindingSource.ListChanged += CompanyBindingSource_ListChanged;
}
I've created a ListChanged method to see when the software does detect that the list has, indeed, changed. In the first code it does trigger, but it doesn't in the second. Maybe the observer isn't detecting the change in the list when I add a filter?
private void CompanyBindingSource_ListChanged(object sender, ListChangedEventArgs e)
{
MessageBox.Show("List changed!");
}
And finally, the add motor button:
private void button1_Click_1(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(textBox1.Text))
{
Motor m = new Motor();
m.company = textBox1.Text;
_context.Motors.Add(m);
_context.SaveChanges();
MessageBox.Show($"New motor, id: {m.motorID}");
}
}
With the first implementation, the comboBox does update and shows every company (for every motor):
Push add button -> "List changed!" popup -> "New motor: id" popup
With the filter:
Push add button -> "New motor: id" popup
In fact the motor adds, but it doesn't show until the restart of the program.
Any idea will be much appreciated. I hope I've explained myself well.
The following line in the second example break the binding:
_context.Motors.Local.ToBindingList().Select(x => x.company).Distinct();
The reason is that the result of .Select(x => x.company).Distinct() is not a BindingList<Motor>, but a simple IEnumerable<string>
Use the following replacement:
var _companies = _context.Motors.Select(x => x.company).Distinct().ToList();
this.companyBindingSource.DataSource = _companies;
This line
this.companyBindingSource.DataSource = _context.Motors.Local.ToBindingList().Select(x => x.company).Distinct();
Returns IEnumerable<T>. In your case you want it to be list, so add .ToList();
this.companyBindingSource.DataSource = _context.Motors.Local.ToBindingList().Select(x => x.company).Distinct().ToList();

Windows Phone 8.1 runtime show message box on OnNavigatedFrom (back button)

I have been fighting with this for a while...
I'm using Windows Phone 8.1 Runtime (not silverlight) and I have the following code:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
if (!ExitWithoutSave().Result) return;
this.navigationHelper.OnNavigatedFrom(e);
}
private async Task<bool> ExitWithoutSave()
{
MessageDialog dialog = new MessageDialog("There are unsaved changes, are you sure you wish to leave?", "Unsaved changes");
dialog.Commands.Clear();
dialog.Commands.Add(new Windows.UI.Popups.UICommand("Yes") { Id = 0 });
dialog.Commands.Add(new Windows.UI.Popups.UICommand("No") { Id = 1 });
dialog.DefaultCommandIndex = 0;
dialog.CancelCommandIndex = 1;
var result = await dialog.ShowAsync();
if (result.Label == "No")
{
canceled = true;
}
return canceled;
}
Basically, I want to ask the user if he wishes to leave without saving, if he says no, then I want to block this functionality.
The problem is, if there's an await during the execution of the OnNavigatedFrom, Windows phone thinks the app has broken and the UI gets blocked.
Is there any way to correctly show a message box on pressing the back button?
If not, is it possible to disable the back button entirely for this page?
Thanks,
Keran
Edit 15-11-2015:
Just wanted to bump this post. I had no luck using HardwareButton events together with Navigation Helper, MessageBoxes still don't work. I can't even cancel the back button press.
So I wanted to renew my question: What is the best way to create a confirm message box on back button press on Windows Phone 8.1 Runtime? F. e. message: "You have unsaved changes, do you wish to exit?": Yes / No.
You can use following event .
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
void HardwareButtons_BackPressed(object sender, BackPressedEventArgs e)
{
}

Categories

Resources