In my activity I am dynamically creating controls based off of sqlite data. Each item will have a button with a click event that needs to send that rows ID to the new activity.
I have looked at the following page and can get this to work on a button that already exists in my layout. But it doesn't seem to work when the button is dynamically created. Is there something additional I need to do with the button for this to work?
https://developer.xamarin.com/recipes/android/fundamentals/activity/pass_data_between_activity/
Here is the code that creates the button dynamically:
foreach (Tasks item in table)
{
TableRow row = new TableRow(this);
TextView txtTask = new TextView(this);
txtTask.Text = item.Name;
row.AddView(txtTask);
tableLayout.AddView(row);
row = new TableRow(this);
Button btnEdit = new Button(this);
btnEdit.Text = "Edit Record";
btnEdit.SetWidth(300);
btnEdit.Click += delegate
{
Intent viewTask = new Intent(this, typeof(UpdateTaskActivity));
viewTask.PutExtra("TaskId", item.Id);
StartActivity(viewTask);
};
row.AddView(btnEdit);
tableLayout.AddView(row);
}
In the OnCreate method of UpdateTaskActivity I have:
string test = Intent.GetStringExtra("TaskId") ?? "error";
if (test != "error")
{
//Do Stuff
}
But when I put a breakpoint down, my string is always null. I did put a breakpoint to make sure the correct ID is being pulled.
Why does this work with a built in button but does not work with my dynamic one?
Just to avoid confusion, in my startup screen I have a test button, and my main activity has the following code for that button. This code works fine, because the button isn't dymaically created:
//Test button
Button btnTest = FindViewById<Button>(Resource.Id.btnTest);
btnTest.Click += delegate
{
var activity2 = new Intent(this, typeof(UpdateTaskActivity));
activity2.PutExtra("TaskId", "1");
StartActivity(activity2);
};
The main issue is that you are adding an int to the extras:
// item.Id is an int type
viewTask.PutExtra("TaskId", item.Id);
And then you are trying to get it as a string:
var test = Intent.GetStringExtra("TaskId");
There are two ways to get the value, without having to add the value as a string. Either get an int value:
var test = Intent.GetIntExtra("TaskId", 0);
if (test != 0)
{
// Do Stuff
}
Or, you can first check for the extra, if you don't want to rely on the default value:
if (Intent.HasExtra("TaskId"))
{
var test = Intent.GetIntExtra("TaskId", 0);
// Do Stuff
}
Related
I'm creating an application to scan barcode tickets. When you start the app a list of available shows has to be shown on the screen. To get all the available shows I'm using a webservice which returns me a List<Event>. How do I create a list of buttons with each button representing a show/event from inside the xaml.cs? When clicking the button a new page will be shown where the user can scan the tickets from that show. I'm pretty new to Xamarin.Forms and I quite don't understand how to use the paging/content views. I already searched a lot but the closest to what I need was this: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/get-started-with-xaml?tabs=vswin
Unfortunatly it only shows how to add a certain amount of controls. And not a dynamicly generated amount.
Many thanks in advance!
In xaml insert a stacklayout where you want your buttons to appear. Remember you can also play whith its Orientation and Spacing properties. So:
<StackLayout x:Name="MyButtons"/>
Then in code-behind generate your dinamic buttons list. Put the code in constructor AFTER InitializeComponent(); or somewhere else:
var myList = new List<*Event or something*>(); //your list here
MyButtons.Children.Clear(); //just in case so you can call this code several times np..
foreach (var item in myList)
{
var btn = new Button()
{
Text = item.*your property*, //Whatever prop you wonna put as title;
StyleId = item.*your ID property* //use a property from event as id to be passed to handler
};
btn.Clicked += OnDynamicBtnClicked;
MyButtons.Children.Add(btn);
}
Add a handler:
private void OnDynamicBtnClicked(object sender, EventArgs e)
{
var myBtn = sender as Button;
// who called me?
var myId = myBtn.StyleId; //this was set during dynamic creation
//do you stuff upon is
switch (myId)
{
case "1": //or other value you might have set as id
//todo
break;
default:
//todo
break;
}
}
How to get Event on selected next Tab
Want to load next tab view controller after event trigger.
It create two tab bar for IOS mobile application.
public class TabBarController : UITabBarController {
UIViewController infoController, relatedController,
public TabBarController ()
{
infoController = new UIViewController();
infoController.Title = "Info";
infoController.TabBarItem = new UITabBarItem ("Info", UIImage.FromFile("/Images/first.png"), 0);
infoControllerView.BackgroundColor = UIColor.Orange;
relatedController = new UIViewController();
relatedController.Title = "Related";
relatedController.TabBarItem = new UITabBarItem ("Related", UIImage.FromFile("/Images/second.png"), 1);
relatedController.View.BackgroundColor = UIColor.Orange;
var tabs = new UIViewController[] {
infoController, relatedController
};
ViewControllers = tabs;}}
Second tab will load after a service call result.
based on response data will show result.
Want to know and Event for tab-bar selected tab.
#All
Thanks you in advance.
I have a form that I would like to reuse for both adding a new record and editing an existing record. I am able to successfully load the page with the relevant data when I select a record from a GridView and I am able to update the db record appropriately. However, my issue is trying to use the form for both executions. Here is my logic in code behind: (I assign a session variable when I click on the row in GridView and this does work successfully)
protected void Page_Load(object sender, EventArgs e)
{
resultOutput.Visible = false;//Output results as to whether or not a record was added successfully is automatically hidden at page load
//Checking to see if session variable has been created
if (Session["editID"] != null)
{
//Create objects to get recipe data
dbCRUD db = new dbCRUD();
Recipe editRecipe = new Recipe();
//Grabbing session ID and assigning to a variable in order to remove the session variable
var id = Convert.ToInt32(Session["editID"]);
Session.Remove("editID");
//Call method to retrieve db data
editRecipe = db.SelectRecord(id);
//Populate results to text boxes
recordID.Text = id.ToString();
addName.Text = editRecipe.Name;
addTypeDDL.SelectedValue = editRecipe.Meal;
addDifficultyDDL.SelectedValue = editRecipe.Difficulty;
addCookTime.Text = editRecipe.Cook_Time.ToString();
addDirections.Text = editRecipe.Directions;
//Change Button Text
submitRecord.Visible = false;
changeRecord.Visible = true;
//Change Title Text
addEditTitle.Text = "Edit Recipe";
}
}
protected void submitRecord_Click(object sender, EventArgs e)
{
//Variables for execution results
var modified = "";
int returned = 0;
//Creating the recipe Object to pull the values from the form and
//send the recipe object as a parameter to the method containing insert stored procedure
//depending on Add or Edit
Recipe recipe = new Recipe();
recipe.Name = addName.Text;
recipe.Meal = addTypeDDL.Text;
recipe.Difficulty = addDifficultyDDL.Text;
recipe.Cook_Time = int.Parse(addCookTime.Text);
recipe.Directions = addDirections.Text;
//Creating object to access insert method
dbCRUD newRecord = new dbCRUD();
//Checking to see if the page is loaded for edit or new addition
if (Session["editID"] != null)
{
//If recordID exists, recipe will be passed as to UpdateRecord method
recipe.Recipe_ID = int.Parse(recordID.Text);
returned = newRecord.UpdateRecord(recipe);
modified = "has been edited.";
Session.Remove("editID");
}
else
{
//If recordID does not exist, record will be passed to InsertRecord method (new recipe)
returned = newRecord.InsertRecord(recipe);
modified = "added";
}
//Method returns 0 if successful, 1 if sql error, 2 if other error
if (returned == 1)
{
resultOutput.Text = "There was an sql exception";
resultOutput.Visible = true;
}
else if (returned == 2)
{
resultOutput.Text = "There was a non sql exception";
resultOutput.Visible = true;
}
else
{
resultOutput.Text = "\"" + addName.Text + "\" recipe " + modified;
resultOutput.Visible = true;
}
}
I have issues on the if(Session["editID"] != null) line - I am always moved to the else logic and the if logic never runs.
Here is my click method in the GridView:
protected void Grid_Recipe_SelectedIndexChanged(object sender, EventArgs e)
{
int index = Convert.ToInt32(Grid_Recipe.SelectedDataKey.Value);
Session["editID"] = index;
Response.Redirect("addRecord.aspx");
}
My question is how can I control execution during the submitRecord_Click event so that I call the appropriate method. Thanks!
Have you considered using
if(Page.IsPostBack)
{
code here
}
To detect whether you are posting back to the page? Then you could check your value of the item. I see no reason the code shouldn't be in the Session variable - have you tried putting a breakpoint in there to see if the code actually gets in there?
Also does your addRecord.aspx just add the record? If so, just add the record in this class, but use the PostBack check to see. Could you just make sure you are saving in the right context aswell:
// Outside of Web Forms page class, use HttpContext.Current.
HttpContext context = HttpContext.Current;
context.Session["editID"] = index;
...
int Id = (string)(context.Session["editID"]);
I was able to figure out my issue - which actually turned into two issues. First, I had to put my Page Load logic in a if(!IsPostBack) statement because I could not edit the page. Reason being is I was loading the originally posted data to the form on page load, which executed before my logic. Adding the if(!IsPostBack) control statement fixed this issue. From there, I'm still using a session variable to control code behind logic, only I made sure keep my session variable only between the form and the gridview. Basically, when the gridview loads and it is not a post back, the session variable is cleared. This let's me set a new session variable when I click on a row and then the session variable is cleared once I return to the grid to see the results. Thanks for the help!
I have a method that adds items to my listbox called refreshInterface which is called as soon as the programe starts, adding names of homeforms in the listbox using the FormItems class, here is the rereshInterface method below
public void refreshInterface()
{
//int number = 0;
foreach (DataSet1.xspGetAnalysisUsageTypesRow homeForms in myDataSet.xspGetAnalysisUsageTypes)
{
var forms = new FormItems(homeForms);
listBox1.Items.Add(forms);
}
}
The FormItems class is this below
public class FormItems
{
public DataSet1.xspGetAnalysisUsageTypesRow types { get; set; }
public FormItems(DataSet1.xspGetAnalysisUsageTypesRow usageTypes)
{
types = usageTypes;
}
public override string ToString()
{
// returns the rows that are relating to types.xlib_ID
var libtyps = types.GetxAnalysisUsageRows();
var cnt = 0;
foreach (DataSet1.xAnalysisUsageRow ty in libtyps)
{
//returns true if ty is null
bool typeNull = ty.Isxanu_DefaultNull();
// if its false, if xanu_Default is set
if (!typeNull)
{
cnt += 1;
}
}
var ret = String.Format("set {0} [Set: {1}]", types.xlib_Desc, cnt);
//return this.types.xlib_Desc;
return ret;
}
}
Each listbox (the listbox is on the left of the homeform) item has a number of reports that can be added to it, so for instance, i select an homeform from my listbox, there are 12 textboxes on the right hand side and each textbox has a pair of buttons which are Browse and Clear. If I click on the browse button a new form appears, and i select a report from that form and add it to a particular textbox, the count for that homeform should update, and i clear a textbox for a particular homeform, the count should also update.
At the moment when i debug the application, it shows me the count of each Homeform depending on the amount of reports added to the homeform, but while the programe is running, if i add a new report to a homeform, the count does not update until i restart the debug session. I was told about using a Databinding method but not sure of how i could use it here
How do i ge my listbox item to update ?
You should probably look into binding. Here is a good place to start:
http://www.codeproject.com/Articles/140621/WPF-Tutorial-Concept-Binding
If you want a GUI to respond to data changes then binding is your best friend.
You should bind List Box component source to Observable Collection, every update you do to Observable Collection will update List Box data.
Might not be exact but should give you an idea.
public void refreshInterface()
{
Dictionary<int,string> items = new Dictionary<int,string>();
//int number = 0;
foreach (DataSet1.xspGetAnalysisUsageTypesRow homeForms in myDataSet.xspGetAnalysisUsageTypes)
{
var formitem = new FormItems(homeForms);
items.Add(formitem.someprop, formitem.toString());
}
listbox.DataSource = items;
listbox.DisplayMember = "Value";
listbox.ValueMember = "Key";
}
I have defined a placeholder in my page like this;
<asp:PlaceHolder ID="attrPlaceHolder" runat="server"></asp:PlaceHolder>
I am populating this place holder from a database table using query string productId like this;
// obtain the attributes of the product
DataTable attrTable = CatalogAccess.GetProductAttributes(productId);
// temp variables
string prevAttributeName = "";
string attributeName, attributeValue, attributeValueId;
// current DropDown for attribute values
Label attributeNameLabel;
DropDownList attributeValuesDropDown = new DropDownList();
// read the list of attributes
foreach (DataRow r in attrTable.Rows)
{
// get attribute data
attributeName = r["AttributeName"].ToString();
attributeValue = r["AttributeValue"].ToString();
attributeValueId = r["AttributeValueID"].ToString();
// if starting a new attribute (e.g. Color, Size)
if (attributeName != prevAttributeName)
{
prevAttributeName = attributeName;
attributeNameLabel = new Label();
attributeNameLabel.Text = "<li class=\"txt\">" + attributeName + ":</li>";
attributeValuesDropDown = new DropDownList();
attrPlaceHolder.Controls.Add(attributeNameLabel);
attrPlaceHolder.Controls.Add(attributeValuesDropDown);
}
// add a new attribute value to the DropDownList
attributeValuesDropDown.Items.Add(new ListItem(attributeValue, attributeValueId));
}
However, when inside a button click event, when I loop through this place using visual studio debugging, I saw that the visual studio studio debugger first hit the "attrPlaceHolder.Controls" word in my foreach loop, then secondly comes to 'in' keyword (in foreach loop) but it isn't hitting the first two words (i-e 'Control cnt' in my foreach loop. Here it looks;
protected void ButtonBuyNow_Click(object sender, EventArgs e)
{
// Retrieve the selected product options
string options = "";
foreach (Control cnt in attrPlaceHolder.Controls)
{
if (cnt is Label)
{
Label attrLabel = (Label)cnt;
options += attrLabel.Text;
}
if (cnt is DropDownList)
{
DropDownList attrDropDown = (DropDownList)cnt;
options += attrDropDown.Items[attrDropDown.SelectedIndex] + "; ";
}
}
// Add the product to the shopping cart
ShoppingCartAccess.AddItem(productId, options);
}
Basically I need 'options' variable to be populated but it isn't hitting the foreach loop inside, therefore I am not able to get the 'options' variable populated.
This is a serious problem in my application. Please tell me why I can't get the inside the foreach loop.
NOTE:
please note that this isn't the complete code of my entire page. My rest of the code executes correctly.
why I can't get the inside the foreach loop
Because the list is empty.
Why is the list empty? (Would be the next logical question)
Because, at ASP.Net, dynamically created controls must be re-created at Page_Init in order to exist. When you create them at this stage, the page lifecycle will bind the viewstate and will be ready for use.
If you receive a postback (from the button, for example) and don't recreate them, they simply don't exist.