web user control adding items problem - c#

On one web user control
public void displayFindingSection(int sectionsid,string text,string head)
{
SectionHeading.Text = head;
DataSet totImgs;
totImgs = objGetBaseCase.GetFindingsNewerImages(sectionsid);
FindingViewerlist.DataSource = totImgs;
DataBind();
SectionText.Text = text;
}
On other web user control
public void DisplayFindingsViewer(CipCaseWorkflowItem2 item)
{
FindingViewerDisplay.Visible = true;
ImageAndSimpleViewer.Visible = false;
objGetBaseCase.GetFindingsImages((Convert.ToInt32(Session["CaseId"])), item.ItemId);
FindingsViewerNew = objGetBaseCase.GetFindingViewerNewElementDetails(item.ItemId);
for (int i = 0; i < FindingsViewerNew.Count; i++)
{
FindingViwerDisplay uc = (FindingViwerDisplay)LoadControl("FindingViwerDisplay.ascx");
FindingPlaceholder.Controls.Add(uc);
uc.displayFindingSection(Convert.ToInt32(FindingsViewerNew[i].Index), FindingsViewerNew[i].Text, FindingsViewerNew[i].Title);
}
}
I am adding the all the image in user control and displaying the image, but when i am using the above code, web user control is also adding every time and one image is showing in in control what i want is all images should show in only one user control.. sectionsid is getting the image id from the database. I think prob with for loop but i am unable to solve it.. help me it that

Might be it is happening u have defined it inside the loop
FindingViwerDisplay uc = (FindingViwerDisplay)LoadControl("FindingViwerDisplay.ascx");
FindingPlaceholder.Controls.Add(uc);
On Each loop you are adding uc and calling displayFindingSection whcich ofcouse add 1 image than loop go back add a new control again and than add one image it will go on till your loop completion so add control once before loop and call just displayFindingSection in loop..
Do this,
FindingViwerDisplay uc = (FindingViwerDisplay)LoadControl("FindingViwerDisplay.ascx");
FindingPlaceholder.Controls.Add(uc);
//define here a dataTabel with three columns let say u have datatable dt
for (int i = 0; i < FindingsViewerNew.Count; i++)
{
dt.Rows.Add(Convert.ToInt32(FindingsViewerNew[i].Index), FindingsViewerNew[i].Text, FindingsViewerNew[i].Title);
}
uc.displayFindingSection(dt);
Then work out on that dt in displayFindingSection
Sorry if i am wrong...

Related

Removing dynamically created HTML table rows - Life Cycle / Viewstate problem

so i have an HTML table with dynamically added rows and ASP.NET text boxes. I have the rows and controls re-instantiated on page_load if the viewstate[dataonpage] = true, and I'm declaring it as true in the method that adds the rows and controls. (I need them to persist on other postbacks)
The problem is that I'm now I've added a CLEAR button that removes all of the html rows (excluding the headers) when it's clicked, and for some reason on button click it gets an index error, or if using Try/Catch it only removes half of the rows (every other row). I believe the problem is something to do with that the viewstate[dataonpage] is still "true", and the data is being re-added on page load. If i add viewstate["dataonpage"] = "false" into the clear button method, the same happens but at least this way on the second click it removes the second half of the rows.
I understand this happens because the button event handler isn't fired until after the page_load which is why it doesn't work on the first click. But what I don't fully understand is why even without this my clear button code doesn't clear all of the rows in the first place.
Any help on understanding why it doesn't work, and a work around will be greatly appreciated!
protected void Page_Load(object sender, EventArgs e)
{
if (Convert.ToString(ViewState["DataOnPage"]) == "true")
{
Getmarketdata();
}
}
protected void Getdatabtn_Click(object sender, EventArgs e)
{
ViewState["DataOnPage"] = "true";
Getmarketdata();
}
Below is method that creates adds table rows and controls:
public void Getmarketdata()
{
String url = "https://api.rightmove.co.uk/api/rent/find?index=0&sortType=1&maxDaysSinceAdded=" + Dayssinceuploadtext.Text + "&locationIdentifier=OUTCODE%5e" + Outcodetext.Text + "&apiApplication=IPAD";
Response.Write(url);
using (var webclient = new WebClient())
{
String Rawjson = webclient.DownloadString(url);
ViewState["VSMarketDataJSONString"] = Rawjson;
dynamic dobj = JsonConvert.DeserializeObject<dynamic>(Rawjson);
int NoOfHouses = dobj["properties"].Count;
Response.Write("<br />" + NoOfHouses);
for (int i = 0; i < NoOfHouses; i++)
{
System.Web.UI.HtmlControls.HtmlTableRow tRow = new System.Web.UI.HtmlControls.HtmlTableRow();
GeneratorTable.Rows.Add(tRow);
String RMlink = String.Format("https://www.rightmove.co.uk/property-to-rent/property-" + dobj["properties"][i]["identifier"].ToString()) + ".html";
HyperLink hypLink = new HyperLink();
hypLink.Text = dobj["properties"][i]["identifier"].ToString();
hypLink.Target = "_blank";
hypLink.NavigateUrl = RMlink;
using (System.Web.UI.HtmlControls.HtmlTableCell tb1 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
tRow.Cells.Add(tb1);
tb1.Controls.Add(hypLink);
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb2 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbEPCe = new TextBox();
tRow.Cells.Add(tb2);
tb2.Controls.Add(tbEPCe);
String txtboxID = (("EPCETxtBox") + i);
tbEPCe.ID = txtboxID;
tbEPCe.Style.Add("background", "none"); tbEPCe.Style.Add("border", "1px solid black"); tbEPCe.Style.Add("border-radius", "2px");
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb3 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbEPCp = new TextBox();
tRow.Cells.Add(tb3);
tb3.Controls.Add(tbEPCp);
String txtboxID = (("EPCPTxtBox") + i);
tbEPCp.ID = txtboxID;
tbEPCp.Style.Add("background", "none"); tbEPCp.Style.Add("border", "1px solid black"); tbEPCp.Style.Add("border-radius", "2px");
}
using (System.Web.UI.HtmlControls.HtmlTableCell tb4 = new System.Web.UI.HtmlControls.HtmlTableCell())
{
TextBox tbBbl = new TextBox();
tRow.Cells.Add(tb4);
tb4.Controls.Add(tbBbl);
String txtboxID = (("BblTxtBox") + i);
tbBbl.ID = txtboxID;
tbBbl.Style.Add("background", "none"); tbBbl.Style.Add("border", "1px solid black"); tbBbl.Style.Add("border-radius", "2px");
}
}
}
}
Below is clear table rows method: (this is the one that isn't working)
public void ClearTableRows()
{
System.Web.UI.HtmlControls.HtmlTable Htmlgeneratortable = ((System.Web.UI.HtmlControls.HtmlTable)GeneratorTable);
int NoOfRows = Htmlgeneratortable.Rows.Count;
for (int j = 1; j < NoOfRows; j++)
{
try
{
Htmlgeneratortable.Rows.RemoveAt(j);
}
catch
{ }
}
}
I'm going to explain what's going on as you have the code written now; I don't have faith in my ability to provide an answer including the exact code changes to be made, so here is what is wrong with your current approach:
Your table, GeneratorTable exists for all clients. That doesn't mean every time someone navigates to your website a table is generated, it means that there is one table, and every client that logs in is getting that one table.
So if you add rows to it for one client, then send the table to another client, both clients will see the same table (with the rows added).
The problem is that emptying out a table is logic that has nothing to do with your back-end server. There's no reason for your server to be handling emptying a table, your server should only handle page navigations and AJAX calls pretty much, it shouldn't be changing how the webpage looks, because the server can only respond to each client one time.
What's the point in responding to a client with GeneratorTable and then updating GeneratorTable on the server? The client will never see the updates made to the table unless they're resent from the server.
You stated that you are new to this and need to learn about JS and client-side, this exercise should serve as an example of why you need to put certain code on the front-end and some code on the back-end, as there isn't really an elegeant way to do what you're looking to do with just the server.

How to add an interator number to a variable name?

In my program i'm currently working on programmatically adding a variety of form objects in C#. For example i'm trying to create a certain group of panels, which contain the data I wish to show. When loading the form I have a file which contains all of the data I wish to load in, the loading itself works fine but when loading I need to create a variety of form labels, panels and images to display all of the necessary data and as such I need to make these panels and labels all with a seperate name, but programmatically.
for (int i=0; i<fileLength; i++)
{
Panel pnl = New Panel();
pnl.Name = "pnl1"+i;
//Set the other properties here
}
What i'm trying to do if use an iterator to append the current iteration to the end of the name. Am I going the right way about it? Or should I be doing a different method?
You cannot change variable/object name at runtime. If you want to write code against the object than you need to keep a reference to it. In your case you have changed the Name property of Panel but still you have to use it as pnl, not as pnl0 or pnl1.
The other way for doing this would be to use a Dictionary with key as the name as you assign and value as the object itself. This will help you in accessing your controls using its name that you have assigned to it.
Dictionary<string, Panel> panels = new Dictionary<string, Panel>();
for (i = 0; i <= 10; i++) {
Panel pnl = new Panel();
panels.Add("pnl" + i.ToString(), pnl);
}
//write code against panels
panels("pnl0").Width = 100;
For accessing within loop:
foreach (string pnlName in panels.Keys) {
panels(pnlName).Visible = true;
}
for (i = 0; i <= 10; i++) {
panels("pnl" + i).Visible = true;
}

Refresh/Update Controls inside usercontrol

I have a form that has TabControl with Dynamic TabPages in it. Each pages has usercontrol added using a loop. This is how I add the usercontrol in each pages.
for (var i = 0; i < tbl.Rows.Count; i++)
{
uctrTab = new XtraTabPagesUserCtrl();
xtab.TabPages[i].Text = "Table " + (i+1);
uctrTab.LayoutClicked += new MouseEventHandler(Layout_Click);
xtab.TabPages[i].Controls.Add(uctrTab);
xtab.TabPages[i].PageVisible = !xtab.TabPages[i].PageVisible;
}
The usercontrol I made has a DataGridView in it so i want to refresh the content of it but I dont know how to do that without removing and readding the control back.
right now my solution is
xtab.SelectedTabPage.Controls.Clear();
uctrTab = new XtraTabPagesUserCtrl();
uctrTab.LayoutClicked += new MouseEventHandler(Layout_Click);
xtab.SelectedTabPage.Controls.Add(uctrTab);
is there any better way of refreshing the content without having to do that?
I'm going to write my answer here (I did it in the comments section because question was on hold).
My suggestion.. first implement a method in your user control like..
public void RefreshGrid()
{
refresh datagridview data here
}
Second, itearate over selected tab page's controls and look for your usercontrol.. something like this..
foreach(Control ctrl in selectedTabPage.Controls)
{
if(ctrl is XtraTabPagesUserCtrl)
{
((XtraTabPagesUserCtrl)ctrl).RefreshGrid();
}
}

How to access TabPages that are created in real-time?

Some inits done earlier in the code...
private List<System.Windows.Forms.TabPage> tab_pages = new List<System.Windows.Forms.TabPage>();
int tab_increment = 0;
Somewhere in the code, I create a bunch of tab pages in real-time.
for (i=0; i<5; i++)
{
tab_pages.Add( new System.Windows.Forms.TabPage() );
tab_pages[tab_increment].Location = new System.Drawing.Point(4, 22);
tab_pages[tab_increment].Name = 1 + tab_increment.ToString();
tab_pages[tab_increment].Size = new System.Drawing.Size(501, 281);
tab_pages[tab_increment].Text = tab_increment.ToString();
this.tabControl.Controls.Add(tab_pages[tab_increment]);
tab_increment += 1;
}
Now I would like to access elements that are these tab pages. Also let's pretend that I created different elements on each page (example, tabPage[0] a button, tabPage[1] a checkbox, etc), how do I access them knowing that everything was added dynamically?
Check this approach:
void Walk(Control control)
{
foreach (Control c in control.Controls)
{
//just walking through controls...
//...do something
//but remember, it could contain containers itself (say, groupbox or panel, etc.)...so, do a recursion
if (c.Controls.Count > 0)
Walk(c);
}
//or
foreach (Button btn in control.Controls.OfType<Button>())
{
//an example of how to walk through controls sub array of certain type
//this loop won't have a single iteration if this page contains no Buttons
//..so you can replace Button
//and have some certain code for different types of controls
}
}
And launch it for tabcontrol:
foreach (TabPage page in tabControl1.TabPages)
Walk(page);
I guess there is no special need to have separate collection of tabpages for one tabcontrol, as soon as it has TabPages property.
In the code above I used Enumerable.OfType Method to get a subcollection of controls of certain type.
As for your code, try this:
for (int i = 0; i < 5; i++)
{
this.tabControl.Controls.Add(new System.Windows.Forms.TabPage());
this.tabControl.TabPages[i].Text = i.ToString();
//...do whatever you need
//...
//besdies, I think, ther's no need in tab_increment...loop index works well enough
}
In order to add pages, I think that using
tabControl.TabPages.Add(new TabPage("Name"));
or in your case
this.tabControl.TabPages.Add(tab_pages[tab_increment]);
is more suitable.
In order to access them you could use
TabPage tp = tabControl.TabPages[i]; //where i is the index of your TabPage
and you can use TabPage.Controls.Add of the Controls property to add any Control on the TabPage like:
Button btn = new Button();
btn.Name = "Button name";
tp.Controls.Add(btn);
You can use the Controls property on the TabPage object. Each control in the collection is given to you as a Control, and it is up to you to cast them to the type that you want.

Dynamically create text inputs (ASP.net/C#)

I have an input field on my page where the user will type in the number of text inputs they want to create. The action for the button is:
int num_flds = int.Parse(a_fld.Text);
for (int i = 0; i < num_flds; i++)
{
TextBox tmp = new TextBox();
tmp.ID = "answer_box" + i;
tmp.Width = Unit.Pixel(300);
answer_inputs.Controls.Add(tmp);
}
Now, I have another button that the user would click after they have filled in all their dynamically-created text boxes. Questions, first of all, am I creating the text boxes dynamically in the correct place? How would I get the values out of the dynamically-created text boxes? (The dynamically-created text boxes are being added to the Panel "answer_inputs".
I recommend reading this and a few other articles about the topic of dynamically created controls. It is not quite as straightforward as you might think. There are some important page lifecycle issues to consider.
When creating web controls dynamically, I find it best to have the controls themselves report in the answers. You can achieve it like this:
Create something in your Page class to store the values:
private readonly Dictionary<TextBox, string> values=new Dictionary<TextBox, string>();
Make a method to act as a callback for the textboxes when their value changes:
void tmp_TextChanged(object sender, EventArgs e)
{
TextBox txt = sender as TextBox;
if(txt!=null)
{
values.Add(txt,txt.Text);
}
}
And then add this method to each textbox as they are added:
int num_flds;
if(!int.TryParse(a_fld.Text,out num_flds))
{
num_flds = 0;
}
for (int i = 0; i < num_flds; i++)
{
TextBox tmp = new TextBox();
tmp.ID = "answer_box" + i;
tmp.Width = Unit.Pixel(300);
answer_inputs.Controls.Add(tmp);
tmp.TextChanged += tmp_TextChanged;
}
Finally, you iterate through the dictionary on callback to see if it holds any values. Do this in the OnPreRender method for instance.
Edit: There is a problem with this, if the number of text fields are decreased on postback. Some safe way to recreate the previous textfields on postback should be employed.

Categories

Resources