I'm quite new to ASP.NET and I need your help.
I'm programming on an application which should help to fix frequent issues. Users can click the displayed cases if it describes their problem. The application searches for more cases or displays a possible solution.
Now what I need for this is some code which creates the buttons dynamically. I googled some ideas and created some code, however I was not able to get it to work.
It works to create the first selection of buttons with the Default_Load method. Also the OnClick event (ButtonClick_System) works fine which means I get the next selection.
From here it starts messing around. The dynamic buttons created in ButtonClick_System don't have a working OnClick action.
Instead of proceeding with ButtonClick_Question (because of btn_system.Command += ButtonClick_Question; in ButtonClick_System) it seems like it just loads the homepage (maybe something wrong with Page_Load?).
The application should do ButtonClick_Question until no more datasets available in database.
I got the following code:
using System;
using System.Configuration;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Data;
using Oracle.DataAccess.Client;
namespace Application
{
public partial class _default : System.Web.UI.Page
{
// Variables
private string app_name = "Application";
// ----- Page_Load ----- //
protected void Page_Load(object sender, EventArgs e)
{
Default_Load();
Session["Application"] = app_name;
}
// ----- Methods ----- //
// Load homepage
public void Default_Load()
{
pnl_default.Visible = true;
pnl_content.Visible = false;
HtmlGenericControl html_default = new HtmlGenericControl();
html_default.TagName = "div";
string cmdString = "(...)";
DataTable dtSystems = OraQueryData(cmdString);
foreach (DataRow dtRow in dtSystems.Rows)
{
int system_id = Convert.ToInt32(dtRow["SYSTEM_ID"]);
string system_name = Convert.ToString(dtRow["SYSTEM_NAME"]);
var btn_system = new Button
{
ID = "btn_" + system_name,
Text = system_name,
CssClass = "sys_buttons"
};
btn_system.Command += ButtonClick_System;
btn_system.CommandArgument = Convert.ToString(system_id);
html_default.Controls.Add(btn_system);
}
plh_default.Controls.Clear();
plh_default.Controls.Add(html_default);
}
// Button OnClick Events
protected void ButtonClick_System(object sender, CommandEventArgs e)
{
pnl_default.Visible = false;
pnl_content.Visible = true;
HtmlGenericControl html_questions = new HtmlGenericControl();
html_questions.TagName = "div";
int system_id = Convert.ToInt32(e.CommandArgument);
string cmdString = "(...)";
DataTable dtQuestions = OraQueryData(cmdString);
foreach (DataRow dtRow in dtQuestions.Rows)
{
string question_id = Convert.ToString(dtRow["FRAGE_ID"]);
string question_text = Convert.ToString(dtRow["FRAGE_TEXT"]);
var btn_system = new Button
{
ID = "btn_question" + question_id,
Text = question_text,
CssClass = "quest_buttons"
};
btn_system.Command += ButtonClick_Question;
btn_system.CommandArgument = Convert.ToString(system_id);
html_questions.Controls.Add(btn_system);
}
plh_content.Controls.Clear();
plh_content.Controls.Add(html_questions);
}
protected void ButtonClick_Question(object sender, CommandEventArgs e)
{
pnl_default.Visible = false;
pnl_content.Visible = true;
HtmlGenericControl html_ChildQuestions = new HtmlGenericControl();
html_ChildQuestions.TagName = "div";
int parent_id = Convert.ToInt32(e.CommandArgument);
string cmdString = "(...)";
DataTable dtChildQuestions = OraQueryData(cmdString);
foreach (DataRow dtRow in dtChildQuestions.Rows)
{
string question_id = Convert.ToString(dtRow["FRAGE_ID"]);
string question_text = Convert.ToString(dtRow["FRAGE_TEXT"]);
var btn_system = new Button
{
ID = "btn_question" + question_id,
Text = question_text,
CssClass = "quest_buttons"
};
btn_system.Command += ButtonClick_Question;
btn_system.CommandArgument = question_id;
html_ChildQuestions.Controls.Add(btn_system);
}
plh_content.Controls.Clear();
plh_content.Controls.Add(html_ChildQuestions);
}
// ----- Oracle Data Query Methods ----- //
// Create and execute query on database
public static DataTable OraQueryData(string cmdString)
{
string conString = ConfigurationManager.AppSettings["Connection"];
OracleConnection oraCon = new OracleConnection(conString);
OracleCommand oraCmd = new OracleCommand(cmdString, oraCon);
OracleDataAdapter oraDtAd = new OracleDataAdapter(oraCmd.CommandText, oraCon);
DataTable dt = new DataTable();
oraCon.Open();
oraDtAd.Fill(dt);
oraCon.Close();
return dt;
}
}
}
If I've understood the issue correctly I think you're using the wrong controls for the wrong usages.
What I'd suggest you need to do is bind the collection of FAQ records to a repeater or some other data set display control. You can then have an event on the repeater which can handle which record ID has been clicked, post back with that value and refresh the collection of data from that (maybe in another repeater). Don't dynamically create buttons and bind events to them otherwise you will end up in a mess.
Hope this helps.
Related
I have the following code which populates an html table from data retrieved from Parse.com.
As you can see the table has buttons in it which are generated as the table gets populated. When clicked, obviously the buttons need to perform an action related to that row of data.
Can anybody help me with the click event please, specifically getting the row index?
At the moment the click event doesn't even seem to trigger the "response.Write" alert. (i'm very new to asp.net though)
using Parse;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
namespace FrogPointCMS
{
public partial class Beacons : System.Web.UI.Page
{
string merchantName;
string myMerchantID;
ParseObject merchantObject;
protected void Page_Load(object sender, EventArgs e)
{
merchantName = Request.QueryString["user"];
myMerchantID = Request.QueryString["merchantID"];
merchantObject = (ParseObject)Session["Merchant"];
getBeacons();
}
public async void getBeacons()
{
MyParseQueries myQuery = new MyParseQueries();
var myBeacons = await myQuery.getMyBeacons(merchantObject);
foreach (ParseObject beacon in myBeacons)
{
string aliasName = "";
string offerType = "N/A";
string offerTitle = "";
string offerDescription = "";
var merchantOb = beacon.Get<ParseObject>("merchantObjectId");
var merchantID = merchantOb.ObjectId;
if (merchantID == myMerchantID)
{
if (beacon.ContainsKey("contentObjectID"))
{
ParseObject content = beacon.Get<ParseObject>("contentObjectID"); // get the content object from parse.
offerType = content.Get<string>("offerType");
offerTitle = content.Get<string>("offerTitle");
offerDescription = content.Get<string>("offerDescription");
}
aliasName = beacon.Get<string>("aliasName");
Button assignNameBtn = new Button();
assignNameBtn.ID = "assignName";
assignNameBtn.Text = "Assign Name";
assignNameBtn.Click += assignNameBtn_Click;
Button assignActionBtn = new Button();
assignActionBtn.ID = "assignAction";
assignActionBtn.Text = "Assign Action";
var tr = new HtmlTableRow();
var checkBox = new HtmlTableCell();
var tableCellName = new HtmlTableCell();
var tableCellButton1 = new HtmlTableCell();
var tableCellButton2 = new HtmlTableCell();
var tableCellAction = new HtmlTableCell();
checkBox.InnerHtml = "<input type=\"checkbox\"/>";
tableCellName.InnerText = aliasName;
tableCellButton1.Controls.Add(assignNameBtn);
tableCellButton2.Controls.Add(assignActionBtn);
tableCellAction.InnerText = offerType + " - " + offerTitle + " - " + offerDescription;
tr.Cells.Add(checkBox);
tr.Cells.Add(tableCellName);
tr.Cells.Add(tableCellButton1);
tr.Cells.Add(tableCellAction);
tr.Cells.Add(tableCellButton2);
beaconTable.Rows.Add(tr);
}
}
}
void assignNameBtn_Click(object sender, EventArgs e)
{
Response.Write("<script type=\"text/javascript\">alert('Button clicked');</script>");
var btn = (Button)sender; // testing
HtmlTableRow row = (HtmlTableRow)btn.NamingContainer; //testing
}
}
}
If you want to do javascript stuff when clicking a button, use OnClientClick
Button b = new Button();
b.OnClientClick = "FunctionName"
And then in the html
<script>
function FunctionName() {
alert('Button clicked');
}
</script>
I have a query that selects a table form my db and displays it on some labels, but if the query finds more the one data row it has to display each one of them in a different tab of the form, how can i archive this.
Code:
try
{
mycon.Open();
string querieslabels = "Select *From Alerts where State = #state && Lv =#lv";
oleDbCmd = new OleDbCommand(querieslabels, mycon);
oleDbCmd.Parameters.Add("#state", OleDbType.VarChar, 10).Value = "Open";
oleDbCmd.Parameters.Add("#lv", OleDbType.VarChar, 2).Value = "1";
OleDbDataReader read1;
read1 = oleDbCmd.ExecuteReader();
read1.Read();
state = read1[4].ToString();
if (state != "Closed")
{
lblNum.Text = read1[0].ToString();
lblpress.Text = read1[1].ToString();
txtDescription.Text = read1[2].ToString();
lblDate.Text = read1[3].ToString();
lblOk.Visible = false;
pictureBox2.Visible = false;
mycon.Close();
}
else
{
//Hides labels and other control's
MakeNotVisible();
MessageBox.Show("No alert found");
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
finally
{
mycon.Close();
}
}
What I'm trying to create is some alert system, if there is more than 1 alert it should display in a different tab. Can some one guide me to the solution for this, any help or suggestion is appreciated.
NOTE: I'm using Win Form.
You could create a UserControl, with code that can display one record from a DataTable. Then you can create TabPages and add one new UC to it for each of your rows. Take care not to add too many pages, say no more than 10-15!
Update I just noticed that you are using a DataReader, not a DataTable. No problem, the same solution will worke here, too: Use the added ShowReader method and call it like below..!
Here is an example:
public partial class DataForm : UserControl
{
public DataTable theTable { get; set; }
public DataForm()
{
InitializeComponent();
}
public int showTableRow(int rowIndex)
{
if (theTable == null) return -1;
if (theTable.Rows.Count < rowIndex) return -2;
DataRow row = theTable.Rows[rowIndex];
label1.Text = row[0].ToString();
label2.Text = row[1].ToString();
label3.Text = row[2].ToString();
return 0;
}
public void showReaderRow(OleDbDataReader DR)
{
label1.Text = DR[0].ToString();
label2.Text = DR[1].ToString();
label3.Text = DR[2].ToString();
}
}
For easier access we'll keep a List:
List<DataForm> theDataPages = new List<DataForm>();
Now we can add DataForm pages to the Tab control tabFormPages from the records in a DataTable; here I limit the number to 5:
for (int r = 0; r < DTL.Rows.Count && r < 5; r++)
{
TabPage page = new TabPage( (r+1).ToString("Record #0" ));
DataForm aForm = new DataForm();
aForm.theTable = DTL;
aForm.Parent = page;
aForm.showTableRow(r);
tabFormPages.TabPages.Add(page);
theDataPages.Add(aForm);
}
For use with a DataReader you could write a read loop like this:
while (DR.Read())
{
TabPage page = new TabPage("Alert #"
+ (tabFormPages.TabPages.Count+1).ToString());
DataForm aForm = new DataForm();
aForm.Parent = page;
aForm.showReaderRow(DR);
tabFormPages.TabPages.Add(page);
theDataPages.Add(aForm);
}
First you add the class to your project: Add - Add Usercontrol.
Now you can open it in the Designer and put in all Labels you need as well as the and put a the code. Also flesh out the showRow method to properly display your data in those Labels..
Now you can add such UCs to TabPages in your Tab like I did above.
If you are using a DataTable you can also make one page display a certain record by calling the showRow again:
theDataPages[0].showRow(DTL.Rows.Count - 1);
This will show the last record in the first TabPage.
If you really need to access field on that UC you can create public properties for those fields and access them like so:
public DataTable theTable { get; set; }
public Label Label1 { get; set; }
//..
public DataForm()
{
InitializeComponent();
Label1 = label1;
//..
}
Now you can access the field(s):
if (theDataPages[0].Label1.Text == "Hiho"
theDataPages[0].Label1.BackColor = Color.Green;
Are you using a WinForms application or a WebForms application? You might need an Accordion control (http://www.codeproject.com/Articles/416521/Easy-WinForms-Accordion-Control) or a Tab Control (http://www.c-sharpcorner.com/UploadFile/mahesh/C-Sharp-tabcontrol/) or something similar. You can dynamically create the tabs in them based on the number of rows in your result.
On Button click event I execute a new query i get a new table but i am unable to populate it on to the same grid view. Is there any why where i can use schema instead of dataTables.
private void GetData()//This method Displays the Datatable onto the Grid
{
int intCount = 0;
int.TryParse(txt_messagecount.Text, out intCount);
DataTable dtData = null;
//dtData = _objIMRSData.GetData(txt_fromdate.Text, txt_todata.Text, txt_messagecount.Text);
dtData = _objIMRSData.GetTransactionData( txt_fromdate.Text, txt_todata.Text,intCount );
grd_transactionLog.DataSource = dtData;
grd_transactionLog.DataBind();
dtData.Clear();
}
//On Button click event I execute a new query i get a new table
//but i am unable to populate it on to the same grid view
protected void btn_next_Click(object sender, EventArgs e)
{
int messageCount = int.Parse(txt_messagecount.Text);
string lastRecord = grd_transactionLog.Rows[messageCount-1].Cells[1].Text;
DataTable dtData1 = null;
//dtData = _objIMRSData.GetData(lastRecord, txt_todata.Text, txt_messagecount.Text);
dtData1 = _objIMRSData.GetTransactionData(lastRecord, txt_todata.Text, messageCount);
//grd_transactionLog.Columns.Clear();
grd_transactionLog.DataSource = dtData1;
grd_transactionLog.DataBind();
dtData1.Clear();
}
Reassign the datasource. In the click event do this.
grd_transactionLog.DataSource = null;
grd_transactionLog.DataSource = dtData1;
Windows: 7 Home Premium
Visual Studio: 2012
Language: C#
SQL: Server 2008
I am binding some labels and an Image to a DataReader, which is reading from a local DataBase.
The header label, and the Image URL of the image are binding properly, but the rest of the labels only get populated after I refresh the page.
The first image shows the page after I clicked on the user profile link. Notice that the 3 labels in the page have incorrect information:
After a full page refresh, the data is displayed properly:
The code goes as follows
private static string _acceptingChallenges = "0";
private static string _curUser;
private static string _website = "[None]";
private static string _dateJoined = DateTime.Now.ToString();
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["user"]))
{
_curUser = (Request.QueryString["user"]);
pnlProfilePublic.Visible = true;
pnlProfilePrivate.Visible = false;
PopulatePublic();
}
else
{
if (!string.IsNullOrEmpty((string) Session["Nickname"]))
{
_curUser = Session["Nickname"].ToString();
pnlProfilePublic.Visible = false;
pnlProfilePrivate.Visible = true;
PopulatePrivate();
}
else
{
Response.Redirect("~/Default.aspx");
}
}
InitiateData();
}
private void InitiateData()
{
if (Master == null) return;
Label lblTitle = (Label)Master.FindControl("lblTitle");
const string strSql = "SELECT * FROM vwGetProfileDetails WHERE memberNickname=#member";
var sqlComm = new SqlCommand(strSql, DataConn.Connect()) { CommandType = CommandType.Text };
sqlComm.Parameters.Add(new SqlParameter("#member", SqlDbType.VarChar, 20)).Value = _curUser;
var rdr = sqlComm.ExecuteReader();
int count = 0;
while (rdr.Read())
{
imgProfile.ImageUrl = rdr["memberAvatarLocation"].ToString();
lblTitle.Text = _curUser + "'s Profile Page";
_acceptingChallenges = rdr["memberAcceptingChallenge"].ToString();
_website = rdr["memberWebsite"].ToString();
_dateJoined = rdr["dateAdded"].ToString();
count = count + 1;
}
rdr.Close();
DataConn.Disconnect();
Response.Write(count);
}
PopulatePublic and PopulatePrivate are called before InitiateData... So they will be stored in the static strings and only populated next time the page is called.
If you are using ASP.Net controls then auto view state will probably be enabled so on postback the controls will be repopulated. So you can do lblWebsite.Text = rdr["memberWebsite"].ToString(); and let ASP.NET manage viewstate.. no need for static strings..
Does _curUser have a value the first time InitiateData is called? I don't think so
Also, you don't want to be using static variables on a web page.
I am using a hashtable to store key-value pairs and I initialize this hashtable (ddl_ht) in the method CreateDropDownLists(). However, when I check the value of "currentItem" in my SelectedIndexChanged method, this value is null. Even though I checked the value of
(string)ddl_ht[key[1]]
in my Watch window and it shows a value (not null). Do you understand why this currentItem is null?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ADONET_namespace;
namespace AddFileToSQL
{
public partial class DataMatch : _Default
{
protected System.Web.UI.WebControls.PlaceHolder phTextBoxes;
protected System.Web.UI.WebControls.PlaceHolder phDropDownLists;
protected System.Web.UI.WebControls.Button btnAnotherRequest;
protected System.Web.UI.WebControls.Panel pnlCreateData;
protected System.Web.UI.WebControls.Literal lTextData;
protected System.Web.UI.WebControls.Panel pnlDisplayData;
protected static string inputfile2;
static string[] headers = null;
static string[] data = null;
static string[] data2 = null;
static DataTable myInputFile = new DataTable("MyInputFile");
static string[] myUserSelections;
static Hashtable ddl_ht = new Hashtable();
// Page Load
private void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
{
this.NumberOfControls = 0;
}
}
// Add DropDownList Control to Placeholder
private void CreateDropDownLists()
{
for (int counter = 0; counter < NumberOfControls; counter++)
{
DropDownList ddl = new DropDownList();
SqlDataReader dr = ADONET_methods.DisplayTableColumns(targettable);
ddl.ID = "DropDownListID " + (counter + 1).ToString();
ddl.DataTextField = "COLUMN_NAME";
ddl.DataValueField = "COLUMN_NAME";
ddl.DataSource = dr;
ddl.DataBind();
//myUserSelections[counter] = "";
ddl.AutoPostBack = true;
ddl.EnableViewState = true; //Preserves View State info on Postbacks
ddl.Style["position"] = "absolute";
ddl.Style["top"] = 100 * counter + 80 + "px";
ddl.Style["left"] = 250 + "px";
ddl.SelectedIndexChanged += new EventHandler(SelectedIndexChanged);
ddl_ht.Add(counter, ddl.SelectedValue);
pnlDisplayData.Controls.Add(ddl);
pnlDisplayData.Controls.Add(new LiteralControl("<br><br><br>"));
pnlDisplayData.Visible = true;
pnlDisplayData.FindControl(ddl.ID);
// pnlDropDownList.FindControl(ddl.ID);
dr.Close();
}
}
protected void SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddl = (DropDownList)sender;
string[] value=(ddl.SelectedValue).Split(' ');
string[] key = ddl.ID.Split(' ');
string currentItem=(string)ddl_ht[key[1]];
//if (String.IsNullOrEmpty(currentItem))
//{
// ddl_ht.Add(key[1], value[0]);
//}
if (currentItem != ddl.SelectedValue)
{
ddl_ht.Remove(key[1]);
ddl_ht.Add(key[1], ddl.SelectedValue);
}
}
// Add TextBoxes Control to Placeholder
private void RecreateDropDownLists()
{
for (int counter = 0; counter < NumberOfControls; counter++)
{
DropDownList ddl = new DropDownList();
SqlDataReader dr = ADONET_methods.DisplayTableColumns(targettable);
ddl.ID = "DropDownListID " + (counter + 1).ToString();
ddl.DataTextField = "COLUMN_NAME";
ddl.DataValueField = "COLUMN_NAME";
ddl.DataSource = dr;
ddl.DataBind();
myUserSelections[counter] = "";
dr.Close();
ddl.AutoPostBack = true;
ddl.EnableViewState = true; //Preserves View State info on Postbacks
ddl.Style["position"] = "absolute";
ddl.Style["top"] = 100 * counter + 80 + "px";
ddl.Style["left"] = 250 + "px";
ddl.SelectedIndexChanged += new EventHandler(SelectedIndexChanged);
pnlDisplayData.Controls.Add(ddl);
pnlDisplayData.Controls.Add(new LiteralControl("<br><br><br>"));
}
}
// Create TextBoxes and DropDownList data here on postback.
protected override void CreateChildControls()
{
// create the child controls if the server control does not contains child controls
this.EnsureChildControls();
// Creates a new ControlCollection.
this.CreateControlCollection();
// Here we are recreating controls to persist the ViewState on every post back
if (Page.IsPostBack)
{
RecreateDropDownLists();
RecreateLabels();
}
// Create these conrols when asp.net page is created
else
{
PopulateFileInputTable();
CreateDropDownLists();
CreateLabels();
}
// Prevent child controls from being created again.
this.ChildControlsCreated = true;
}
}
}
You are going to have all kinds of threading problems with this setup. Your hashtable is static, and every hit on your website is going to create a new instance of your class on a new thread that will try to access the same hashtable - and since each new hit to the page will initially call CreateDropDownLists, your hashtable will be reinitialzed for every new user to the page.
You shouldn't store your HashTable as a static field of your page class, since it will be shared between sessions because the life cycle of a static variables in ASP.NET is within the life of the appdomain, consider storing it in the ViewState:
private Hashtable ddl_ht
{
get
{
return ViewState["ddl_ht"] as HashTable;
}
set
{
ViewState["ddl_ht"] = value;
}
}