ASP dynamic usercontrols in a gridview do not update - asp.net

I have a got Gridview, that gets its data by:
internal void updateGrid()
{
List<String> data = dt.getAlldata(UserID(), ListID());
gridViewer.DataSource = data;
gridViewer.DataBind();
}
After a button click the database is updated and the new data is shown. Everything works fine.
Now I have to replace the string with an Usercontrol:
internal void updateGrid()
{
List<String> data = dt.getAlldata(UserID(), ListID());
gridViewer.DataSource = data;
gridViewer.DataBind();
for (int i = 0; i < gridViewer..Rows.Count; i++)
{
UCControl dum = (UCControl)LoadControl("~/UCControl.ascx");
dum.SetData(gridViewer.Rows[i].Cells[0].Text, false);
gridViewer.Rows[i].Cells[0].Controls.Clear();
gridViewer.Rows[i].Cells[0].Controls.Add(dum);
}
}
After first Page_Load(), everything is shown correctly. But when I click my buttons, the Usercontrols do not repaint. The data is set correctly inside, but it does not update.
Because this Control reacts by javascript on UserInputs on the client side, every Usercontrol has got his own Id that is set by
this.ID = "UCControl" + data[0];
data[0] is unique, but known during the whole process.
Can somebody tell me why the UserControl does not repaint? Or better: How do I tell the Usercontrols to update?

From your code I would say that once the data is bound then you can't go in immediately after and start to change it. You would need to hook into one of the databinding events.
If you were using a list viem ItemDataBound would be a good candidate to hook into. But the GridView has a more limited set of events and doesn't offer that level of control - so you are a bit stuck on that score.
In my experience using dynamic controls in asp.net (LoadControl) is just a bit fraught. I think a better option would be to publicly expose a property in your user control and bind to that.
This question gives a good description of how to achieve this
asp.net user controls binds inside gridview
Hope that helps

Related

asp.net - best way to display 5 records at a time using two pages

I have to create a asp.net page that shows 5 records, stays for 10 seconds, shows the next 5 for another 10 seconds and return to the first 5 record when reaching last record.
I need to retrieve data from database every 5 min only to do refresh for the displayed record. I want to do this in 2 different pages - for example one page does all the work and the second page only displays data without doing anything with the database. So whenever there is any problem with the database the first page will keep on showing the last records.
I figured out the first part by using a grid view and timer but I struggled with the second.
It is a notice page like flight information board idea at airports.
I hope you can help me with it or tell me what is the best way to do it.
I would suggest using a usercontrol inside your aspx page, then in your aspx page you can have it check the database and retrieve the data pass it to your usercontrol and databind. If your aspx page cannot retrieve data then it wouldn't databind your usercontrol so it will not change its data.
usercontrol
private DataTable _newdata = null;
public DataTable NewData
{
get { return _newdata; }
set { _newdata = value; }
}
public override void DataBind()
{
if(NewData.Rows.Count > 0)
{
mygridview.DataSource = NewData;
mygridview.DataBind();
}
}
I would recomment doing it on client side using Java Script/JQuery. JQuery JCycle plugin will do it for you

What code do I type in next page after passing gridview button clicked rowindex

I pass the row index value into next page when gridview button clicked using this code
if(e.CommandName=="select")
{
int Id = int.Parse(e.CommandArgument.ToString());
//Label1.Text = Id.ToString();
Response.Redirect("~/manclothes1.aspx?Id=" + e.CommandArgument.ToString());
}
but i don't know what code i write in next page to display row data
please can anyone help me
In ASP.NET you don't actually pass code to a new page. Instead you modify the controls on the current page and the ASP.NET framework re-renders the page for you. Instead of the Response.Redirect line you want something like
DataGrid1.EditItemIndex = Id;
In the page_load of manclothes1.aspx you can try
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["Id"] != null)
{
var id = Request.QueryString["Id"];
// do something with id variable
...
}
}
You'll probably want to reference whatever code on the current page populates the gridview with data in the first place. Essentially, where the code on the current page gets many rows to populate a gridview, the code on the manclothes1.aspx page will get one row. If it's data from a database, the query will likely be very much the same but with an additional WHERE clause to filter by (I'm assuming) an ID value, which is probably a primary key (or the primary key, if we're talking about only one table).
To put this into context, what the call to Response.Redirect() is doing is telling the client (browser) to issue an entirely new request (a GET request, that is) for an entirely new resource (manclothes.aspx with a query string parameter). So understand that "the next page" knows nothing of the gridview on the current page. Nor should it, really. The request should be handled entirely separate from the current page.

Programmatically add UserControl with events

I need to add multiple user controls to a panel for further editing of the contained data. My user control contains some panels, dropdown lists and input elements, which are populated in the user control's Page_Load event.
protected void Page_Load(object sender, EventArgs e)
{
// populate comparer ddl from enum
string[] enumNames = Enum.GetNames(typeof (SearchComparision));
var al = new ArrayList();
for (int i = 0; i < enumNames.Length; i++)
al.Add(new {Value = i, Name = enumNames[i]});
scOperatorSelection.DataValueField = "Value";
scOperatorSelection.DataTextField = "Name";
...
The data to be displayed is added to the user control as a Field, defined above Page_Load. The signature of the events is the following:
public delegate void ControlStateChanged(object sender, SearchCriteriaEventArgs eventArgs);
public event ControlStateChanged ItemUpdated;
public event ControlStateChanged ItemRemoved;
public event ControlStateChanged ItemAdded;
The update button on the user control triggers the following method:
protected void UpdateCriteria(object sender, EventArgs e)
{
var searchCritCtl = (SearchCriteria) sender;
var scEArgs = new SearchCriteriaEventArgs
{
TargetCriteria = searchCritCtl.CurrentCriteria.CriteriaId,
SearchComparision = ParseCurrentComparer(searchCritCtl.scOperatorSelection.SelectedValue),
SearchField = searchCritCtl.scFieldSelection.SelectedValue,
SearchValue = searchCritCtl.scFilterValue.Text,
ClickTarget = SearchCriteriaClickTarget.Update
};
if (ItemUpdated != null)
ItemUpdated(this, scEArgs);
}
The rendering page fetches the data objects from a storage backend and displays it in it's Page_Load event. This is the point where it starts getting tricky: i connect to the custom events!
int idIt = 0;
foreach (var item in _currentSearch.Items)
{
SearchCriteria sc = (SearchCriteria)LoadControl("~/content/controls/SearchCriteria.ascx");
sc.ID = "scDispCtl_" + idIt;
sc.ControlMode = SearchCriteriaMode.Display;
sc.CurrentCriteria = item;
sc.ItemUpdated += CriteriaUpdated;
sc.ItemRemoved += CriteriaRemoved;
pnlDisplayCrit.Controls.Add(sc);
idIt++;
}
When first rendering the page, everything is displayed fine, i get all my data. When i trigger an update event, the user control event is fired correctly, but all fields and controls of the user control are NULL. After a bit of research, i had to come to the conclusion that the event is fired before the controls are initialized...
Is there any way to prevent such behavior / to override the page lifecycle somehow? I cannot initialize the user controls in the page's Init-event, because i have to access the Session-Store (not initialized in Page_Init).
Any advice is welcome...
EDIT:
Since we hold all criteria informations in the storage backend (including the count of criteria) and that store uses the userid from the session, we cannot use Page_Init... just for clarification
EDIT #2:
I managed to get past some of the problems. Since i'm now using simple types, im able to bind all the data declaratively (using a repeater with a simple ItemTemplate). It is bound to the control, they are rendered in correct fashion. On Postback, all the data is rebound to the user control, data is available in the OnDataBinding and OnLoad events, everything looks fine.
But as soon it enters the real event (bound to the button control of the user control), all field values are lost somehow...
Does anybody know, how the page lifecycle continues to process the request after Databinding/Loading ? I'm going crazy about this issue...
Dynamic controls are can be a nightmare. The trick is to make sure you rebind everything on the postback.
I figured out a solution ;)
If i work with the OnCommand event on the buttons inside the usercontrol, i can pass a CommandArgument. Now im binding the collection identifier to the CommandArgument parameter of the button which enables me to handle all postbacks inside the usercontrol.
<asp:Button ID="scUpdate"
runat="server"
Text="Update"
OnCommand="HandleCommand"
CommandName="update"
CommandArgument='<%# CriteriaId %>' />
This declaration preserves the CriteriaId (a Guid) throughout postbacks and enables me to identify the modified entry on the underlying collection (managed on the page). The following code snippet shows how the event to the subscribing page is triggered.
scEArgs = new SearchCriteriaEventArgs
{
TargetCriteria = new Guid(e.CommandArgument.ToString()),
SearchComparision = ParseCurrentComparer(),
SearchField = scFieldSelection.SelectedValue,
SearchValue = scFilterValue.Text,
ClickTarget = SearchCriteriaClickTarget.Update
};
if (ItemUpdated != null)
ItemUpdated(this, scEArgs);
Maybe this answer helps somebody so i'll just post it ;)

How to get a handle to a dynamic imagebutton in an ajax panel postback

I write an imagebutton to a table cell in a new row when a user selects an item in a list:
ImageButton imgbtnRemove = new ImageButton();
imgbtnRemove.ID = "uxStandardLetterDeleteImage_" + items.letterName;
imgbtnRemove.CommandName = "uxStandardLetterDeleteImage_" + items.letterName;
imgbtnRemove.ImageUrl = items.remove;
imgStatus.AlternateText = "Remove";
tRow.Cells[3].Controls.Add(imgbtnRemove);
When the new imagebutton is clicked, I can't seem to get a handle to it. I see it in Page_PreRender event, where I also reload the table on each postback.
string returnData = Request.Form.ToString();
but iterating through the form controls images:
if (c is System.Web.UI.WebControls.Button ||
c is System.Web.UI.WebControls.ImageButton)
does not find it. I can find it if I manually put in a:
imgbtnRemove.Click += new System.Web.UI.ImageClickEventHandler(this.ButtonClick);
in the Page_Load and then grab it in the click event:
switch (((System.Web.UI.WebControls.ImageButton)sender).CommandName)
...
but because there are new rows being added and deleted, this gets rather ugly programmatically. I'm thinking there must be an elegant solution to dynamic imagebutton creation and retrieval on the fly from server side code. I've done a lot of digging but this one is stumping me.
Thanks in advance...
If you're creating dynamic controls during the event handling phase of the Page lifecycle (for example, in the item selected event), then the control will be gone on the next postback.
In order for dynamic controls to be registered with ViewState, they have to be created in the Init phase of the event lifecycle.
Also, you say you're iterating through the Form's controls... when you are adding the imagebutton to the table's cells. Are you recursively descending the control heirarchy to look for the imagebutton?

I want to add items to an ASP.Net combobox using Javascript

I want to add an item to an ASP.Net combobox using Javascript. I can retrieve the ID (No Masterpage). How can I add values to the combobox from Javascript? My present code looks like this.
//Fill the years (counting 100 from the first)
function fillvarYear() {
var dt = $('#txtBDate').val();
dt = dt.toString().substring(6);
var ye = parseInt(dt);
//Loop and add the next 100 years from the birth year to the combo
for (var j = 1; j <= 100; j++) {
ye += 1; //Add one year to the year count
var opt = document.createElement("OPTION");
opt.text = ye;
opt.value = ye;
document.form1.ddlYear.add(opt);
}
}
To see the value on postback:
string selectedValue = Request.Params[combobox.UniqueId]
Remember, changing the values in a combobox with javascript will cause an Event Validation exception to be thrown, and is generally a bad idea, as you'll have to explicitly disabled event validation.
I'd recommend placing the combobox in an update panel, so you can read txtBirthDate on the server and generate the appropriate data. You then won't have to manually preserve state either.
Always remember, ASP.NET controls are nothing "fancy" - they always end up at some point becoming standard HTML elements.
Try checking out this site. It has a pretty nice demo and overview. Take note however that you are altering the data at the client side - this means you will need to do it on each and every request because the ViewState will not be updated.
TBH, you are probably better off just using a HTML control rather than ASP ComboBox..
Can I ask why you are changing items via Javascript? (out of curiosity) :)
I found a possible solution. I don't know why the earlier code didn't work for me, but the line below
document.form1.ddlYear.appendChild(new Option(ye, ye));

Resources