Xamarin Android Pass Data Between Fragments - android-fragments

I create Android Project in Xamarin plugin for Visual Studio Community 2015. I have in my application 4 fragments and I switch in them by ViewPager which is navigated in ActionBar. In second and third tab, there are few fields (for second tab -> Name, Surname, Mail, Phone and for third -> description field). These fields are EditText. On last fragment there are fields (TextView) and I need to pass data from 2nd, 3rd to 4th fragment. These data is only string value.
I try to use this code:
public void OnTabSelected(ActionBar.Tab tab, FragmentTransaction ft)
{
viewPager.CurrentItem = tab.Position;
if (tab.Position == 0)
{
actionBar.SetTitle(Resource.String.GalleryTab);
} else if (tab.Position == 1)
{
actionBar.SetTitle(Resource.String.DescriptionTab);
} else if (tab.Position == 2)
{
actionBar.SetTitle(Resource.String.ContactInfoTab);
} else if (tab.Position == 3)
{
actionBar.SetTitle(Resource.String.SummaryTab);
nameContact.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) =>
{
nameSummary.Text = e.Text.ToString();
};
}
nameContact and nameSummary are properly initialized.
var nameContact = FindViewById<EditText>(Resource.Id.nameContactText);
var surnameContact = FindViewById<EditText>(Resource.Id.surnameContactText);
var nameSummary = FindViewById<TextView>(Resource.Id.nameSummary);
var surnameSummary = FindViewById<TextView>(Resource.Id.surnameSummary);
Can someone explain me how to send data between fragments. Thank you for answer.
UPDATE
I just do something like this.
var nameContact = FindViewById<EditText>(Resource.Id.nameContactText);
nameContactText = nameContact.Text.ToString();
var nameContactSummary = FindViewById<TextView>(Resource.Id.nameSummary);
nameContactSummary.Text = nameContactText;

A way to do it is to store data you need to transfer in parent activity (assuming that both fragments are hosted in the same activity) so every fragment will have access to this data using (Activity as yourActivityType).YourPropertyName in every fragment.
More details on Communicating with the Activity from Fragment can be found here:http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

Related

Nested subscription to messages on xamarin forms

I'm new with Xamarin forms and don't know how to deal with this case. I've tryed to implement it in several ways but with no success.
I have a page where when user makes an action (write a text on a text box and send it with enter key) my app must make some checkings. Depending on the result of the checks, it could be necessary to show a modal page with a list of item to select. Ones user makes the selection process must continue with other checks. And here is my problem, because in this next checkings I have to show another page. User must make a selection/enter some date, and then continue to complete the proccess, but this page is not appear.
I'm using the messagingCenter to subscribe to the modal pages. First modal page appears and makes the selection well. Second modal page is never shown and then proccess never complets.
Here is some of my code:
NavigationPage navigationPage = new NavigationPage(new ListItemsPage(products));
Navigation.PushModalAsync(navigationPage);
MessagingCenter.Subscribe<ListItemsPage, Guid?>(this, "Select product", (obj, item) =>
{
try
{
if (item != null)
{
product = products.SingleOrDefault(x => x.Guid == item);
if (product != null) ProcessLine(product);
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
MessagingCenter.Unsubscribe<ListItemsPage, Guid?>(this, "Select product");
}
});
On ListItemsPage I have this code whe item is selected:
private void MenuItem_Clicked(object sender, EventArgs e)
{
// some logic...
Navigation.PopModalAsync();
MessagingCenter.Send(this, "Select product", SelectedGuid);
}
SelectedGuid is a Guid type data and when debbugin is well selected.
Problems comes when goes to ProcessLine method.
private void ProcessLine(Product product) {
// make some logic...
NavigationPage navigationPage = new NavigationPage(new ControlUnitsPage(model));
Navigation.PushModalAsync(navigationPage);
MessagingCenter.Subscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", (obj, item) =>
{
try
{
if (item != null)
{
_date = item.Date;
_code = item.Code;
_units = item.Units;
Save(productLine, product, _units, _date,_code);
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
MessagingCenter.Unsubscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code");
}
});
}
ControlUnitsPage has the same structure as the last one page. First makes a PopModalAsync and then sends the message sending an instance of ControlUnits type.
private void Button_Clicked(object sender, EventArgs e)
{
//some logic...
Item = new ControlUnits() { Date = DateField.Date, Code = CodeField.Text, Units = int.Parse(SelectedUnits.Value.ToString()) };
Navigation.PopModalAsync();
MessagingCenter.Send(this, "Select units, date and lot code", Item);
}
I think problem is in the order of invoking method but dont know what is the properly order because I am not able to understand how pushmodal, popmodal methods work, whether or not I should use await with it if after that comes a subscription. I really don't know and I need help, please.
Thank you so much!
your Send and Subscribe calls both need to use matching parameters
if Subscribe looks like this
MessagingCenter.Subscribe<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", (obj, item) => ... );
then Send needs to match
MessagingCenter.Send<ControlUnitsPage, ControlUnits>(this, "Select units, date and lot code", Item);

how to update Visual Studio UI when using DynamicItemStart inside a vsix package

I'm implementing a DynamicItemStart button inside a Menu Controller. I'm loading the dynamic items for this button when Visual Studio starts. Everything is loaded correctly so the initialize method is called an I see all the new items in this Dynamic button. After the package is completely loaded I want to add more items to this Dynamic button, but since the package is already loaded the initialize method is not called again and I cannot see the new items in this Dynamic button. I only see the ones that were loaded when VS started.
Is there any way that I can force the update of this Dynamic button so it shows the new items?. I want to be able to update the VS UI after I added more items but outside the Initialize method.
The implementation I did is very similar to the one showed on this msdn example:
http://msdn.microsoft.com/en-us/library/bb166492.aspx
Does anyone know if an Update of the UI can be done by demand?
Any hints are greatly appreciated.
I finally got this working. The main thing is the implementation of a derived class of OleMenuCommand that implements a new constructor with a Predicate. This predicate is used to check if a new command is a match within the DynamicItemStart button.
public class DynamicItemMenuCommand : OleMenuCommand
{
private Predicate<int> matches;
public DynamicItemMenuCommand(CommandID rootId, Predicate<int> matches, EventHandler invokeHandler, EventHandler beforeQueryStatusHandler)
: base(invokeHandler, null, beforeQueryStatusHandler, rootId)
{
if (matches == null)
{
throw new ArgumentNullException("Matches predicate cannot be null.");
}
this.matches = matches;
}
public override bool DynamicItemMatch(int cmdId)
{
if (this.matches(cmdId))
{
this.MatchedCommandId = cmdId;
return true;
}
this.MatchedCommandId = 0;
return false;
}
}
The above class should be used when adding the commands on execution time. Here's the code that creates the commands
public class ListMenu
{
private int _baselistID = (int)PkgCmdIDList.cmdidMRUList;
private List<IVsDataExplorerConnection> _connectionsList;
public ListMenu(ref OleMenuCommandService mcs)
{
InitMRUMenu(ref mcs);
}
internal void InitMRUMenu(ref OleMenuCommandService mcs)
{
if (mcs != null)
{
//_baselistID has the guid value of the DynamicStartItem
CommandID dynamicItemRootId = new CommandID(GuidList.guidIDEToolbarCmdSet, _baselistID);
DynamicItemMenuCommand dynamicMenuCommand = new DynamicItemMenuCommand(dynamicItemRootId, isValidDynamicItem, OnInvokedDynamicItem, OnBeforeQueryStatusDynamicItem);
mcs.AddCommand(dynamicMenuCommand);
}
}
private bool IsValidDynamicItem(int commandId)
{
return ((commandId - _baselistID) < connectionsCount); // here is the place to put the criteria to add a new command to the dynamic button
}
private void OnInvokedDynamicItem(object sender, EventArgs args)
{
DynamicItemMenuCommand invokedCommand = (DynamicItemMenuCommand)sender;
if (null != invokedCommand)
{
.....
}
}
private void OnBeforeQueryStatusDynamicItem(object sender, EventArgs args)
{
DynamicItemMenuCommand matchedCommand = (DynamicItemMenuCommand)sender;
bool isRootItem = (matchedCommand.MatchedCommandId == 0);
matchedCommand.Enabled = true;
matchedCommand.Visible = true;
int indexForDisplay = (isRootItem ? 0 : (matchedCommand.MatchedCommandId - _baselistID));
matchedCommand.Text = "Text for the command";
matchedCommand.MatchedCommandId = 0;
}
}
I had to review a lot of documentation since it was not very clear how the commands can be added on execution time. So I hope this save some time whoever has to implement anything similar.
The missing piece for me was figuring out how to control the addition of new items.
It took me some time to figure out that the matches predicate (the IsValidDynamicItem method in the sample) controls how many items get added - as long as it returns true, the OnBeforeQueryStatusDynamicItem gets invoked and can set the details (Enabled/Visible/Checked/Text etc.) of the match to be added to the menu.

Passing Listview OnClick to Fetch Data from DB

I have a ListView which displays static data along with images (say Activity A). When I click a ListVoew Item, the data is captured and passed onto next Activity (lets call it Activity B). In Activity B, I want to pass the selected value into DB select where clause and fetch data and show relevant information pertaining to the selection. Here is my code snippet...
Activity A:
String subproduct = ((TextView) view.findViewById(R.id.product_label)).getText().toString();
// Launching new Activity on selecting single List Item
SharedPreferences sharedPreferences = getSharedPreferences("pref",MODE_WORLD_READABLE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.clear();
editor.putString("subproduct", subproduct);
editor.commit();
Intent myIntent = new Intent(getApplicationContext(),Details.class);
startActivity(myIntent);
And here is my Activity B:enter code here
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.details1);
SharedPreferences myPrefs = this.getSharedPreferences("pref", MODE_WORLD_READABLE);
String subproduct = myPrefs.getString("subproduct","null");
TextView txtProduct1 = (TextView) findViewById(R.id.detail_item);
txtProduct1.setText(subproduct);
and here is my DBHelper.java. Here I want to pass the selected value. Please help me how I can acheive this...
public Cursor getData(){
//SharedPreferences myPrefs = this.getSharedPreferences("pref", 0);
//String subproduct = myPrefs.getString("subproduct","null");
Cursor c = myDataBase.rawQuery("SELECT * FROM Destmain WHERE destname= " + ? + " ", null);
while (c.moveToNext()){
DestInfo q = new DestInfo();
q.setDestination(c.getString(1));
q.setCity(c.getString(2));
q.setCountry(c.getString(3));
q.setPeriod(c.getString(4));
q.setType(c.getString(5));
q.setCurrency(c.getString(6));
q.setBriefhistory(c.getString(7));
q.setHighlights(c.getString(8));
}
c.close();
return c;
Can anyone help me how I can pass the ListView (Activity A) selected value into fetching DB data and show in Activity B? Thanks a ton.
By using method onItemcClick in Activity A you can get the Id and pass it to the second Activity B.
onItemClick(AdapterView<?> adapterView, View view, int pos, long id)
newActivity.putExtra("key", id);
then in Activity B you can use this Id to search on the Database.
Intent newActivity = getIntent();
long id = newActivity.getLongExtras("key", -1);
in some other case you can use getLunchDetails method

DevExpress XtraScheduler hanging on adding appointment to Storage

I have a XtraScheduler SchedulerControl configured as the following:
private DevExpress.XtraScheduler.SchedulerControl _SchedulerControl;
public DevExpress.XtraScheduler.SchedulerControl ConvSchedulerControl
{
get
{
if (_SchedulerControl == null)
{
_SchedulerControl = new DevExpress.XtraScheduler.SchedulerControl();
_SchedulerControl.Storage = new SchedulerStorage();
_SchedulerControl.Storage.Appointments.Mappings.Subject = "StandingOrderIDString";
_SchedulerControl.Storage.Appointments.Mappings.Start = "ScheduledDate";
_SchedulerControl.Storage.Appointments.Mappings.RecurrenceInfo = "RecurrenceInfo";
_SchedulerControl.Storage.Appointments.Mappings.Type = "Type";
_SchedulerControl.Storage.Appointments.CustomFieldMappings.Add(new DevExpress.XtraScheduler.AppointmentCustomFieldMapping("Inactive", "Inactive"));
_SchedulerControl.Storage.Appointments.CustomFieldMappings.Add(new DevExpress.XtraScheduler.AppointmentCustomFieldMapping("StandingOrderKEY", "StandingOrderKEY"));
BindingSource bs = new BindingSource();
bs.DataSource = new List<StandingOrder>();
_SchedulerControl.Storage.Appointments.DataSource = bs;
}
return _SchedulerControl;
}
}
and I am attempting to programmatically add an appointment with recurrence information, as in the examples given at http://help.devexpress.com/#WindowsForms/CustomDocument6201 . However, when the method execution reaches its final line (indicated) that adds the created appointment to the storage, it "hangs." No exception is ever thrown; I have left it running for upwards of 15 minutes with no change:
public void SetRecurrence(DateTime startDate, DateTime? endDate)
{
Appointment appointmentObj = ConvSchedulerControl.Storage.CreateAppointment(AppointmentType.Pattern);
if (endDate != null &&
endDate != DateTime.Parse("12/31/2999"))
{
appointmentObj.End = (DateTime)endDate;
}
else
{
appointmentObj.RecurrenceInfo.Range = RecurrenceRange.NoEndDate;
}
appointmentObj.Start = startDate;
appointmentObj.RecurrenceInfo.Type = RecurrenceType.Weekly;
appointmentObj.RecurrenceInfo.WeekDays = WeekDays.Monday;
appointmentObj.AllDay = true;
//Program execution reaches this line, but never proceeds past it.
ConvSchedulerControl.Storage.Appointments.Add(appointmentObj);
}
I would imagine that there's something wrong with the configuration that's preventing the storage from being able to successfully add the appointment, but I've been unable to turn up any other information on the subject. Does anyone know why this method isn't appropriate for adding an appointment to the storage, and how it can be corrected?
You've failed to provide a mapping for the 'End' field. This is a required mapping. Honestly, I only know this from having created a calendar in the designer. When you place a SchedulerControl onto a form/control, one of the things the designer gives you is a "Mappings Wizard". The 'Start' and 'End' fields are marked in the wizard as being required.

How do I Immediately Validate a Newly Inserted Row in a Silverlight 3 Datagrid?

I have a Silverlight 3 tools library with a custom DataGrid user control. This grid has no direct access to the WCF RIA Services entity types so I'm using reflection to add a new item when the user clicks on the grid when it's empty:
private void InsertEmptyRecord()
{
if (this._dataGrid.ItemsSource == null)
return;
Type[] typeParameters = this._dataGrid.ItemsSource.GetType().GetGenericArguments();
if (typeParameters.Count() > 0)
{
Type itemType = typeParameters[0];
object newItem = System.Activator.CreateInstance(itemType);
Type sourceType = typeof(System.Windows.Ria.EntityCollection<>);
Type genericType = sourceType.MakeGenericType(itemType);
System.Reflection.MethodInfo addMethod = genericType.GetMethod("Add");
addMethod.Invoke(this._dataGrid.ItemsSource, new object[] { newItem });
// == Validate data here ==
}
}
This works, but I need it to also validate after the new item is added. There are two ways I can see to do this:
Force the user to enter edit mode
for the first cell of the new row in
the grid. (This would force
validation if they click anywhere
else on the page.)
Force validations
to run immediately when the new row
is added (or when the grid looses
focus.)
I haven't been able to get either of these to work. Tried this but it only selects the row, doesn't force the validations to run:
this._dataGrid.SelectedItem = newItem;
System.ComponentModel.IEditableObject editableItem = newItem as System.ComponentModel.IEditableObject;
if (editableItem != null)
editableItem.BeginEdit();
Any suggestions?
Just got this working thanks to some help from this question.
I added the following to the "== Validate data here ==" section in the code from above:
DataGridRow newRow = this._dataGrid.ChildrenOfType<DataGridRow>().FirstOrDefault();
if (newRow != null)
{
newRow.Loaded += (sender, e) =>
{
this._dataGrid.CurrentItem = newItem;
this._dataGrid.BeginEdit();
};
}
This forces the first cell to immediately go into edit mode.

Resources