Asp.net GridView - how to access datasource before data is bound? - asp.net

I'm trying to access datasource before I bind it to grid. How do I do that? My guess I should look in one of the events like Grid.DataBinding

Yes, the GridView.DataBinding event will be raised prior to the control being bound. You can access the DataSource control in that event and make modifications if you so desire (for example, modifying parameters).
protected void Grid_DataBinding(object sender, EventArgs e)
{
mySqlDataSource.SelectCommand = "Select * from Stars";
}

One way would be to not define the datasource on the grid itself. In the page_load, create and populate your datasource and then dynamically bind it to your datagrid. That way you would be able to access it.
Hope it helps!

Related

When does data load in ASP .NET control?

I'm working on a ASP .NET control (for Blackbaud's NetCommunity system) that needs to load data from the database, then update some controls' enabled state based on the data that has been loaded. From what I can see according to Microsoft's page lifecycle, the appropriate place to change this is during the Page_PreRenderComplete event, but this doesn't seem to work, so I'm guessing that I am wrong. However, I don't know for sure since I can't see where the actual database retrieval is taking place. I have two drop downs on this control that determine what data is shown in a grid below, and the grid needs to change its state based on the data inside. Do I need to figure out how to load the data early, and then make my state updates, or is there somewhere I can make the updates late and still have it render properly?
Page_PreRenderComplete is too late to manipulate a control. Normally, we use PreRender event.
However, if you want to manipulate controls located inside GridView, you want to use GridView's RowDataBound event in which you can find controls using FindControl.
For example,
protected void GridView1_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
var textbox = e.Row.FindControl("MyTextBox") as TextBox;
}
}

How can I refresh my FormView after an edit?

I am using a FormView to select companies from a database. This FormView is bound to an ObjectDataSource, which is bound to a DropDownList. When a user selects a company from the DropDownList, the FormView is populated with information pertaining to the company (AutoPostBack is enabled on the DropDownList to provide dynamic record changing). My FormView supports insert, update, and delete functions, of which all three work.
My problem is as follows: After I edit a record in the FormView, the record successfully changes, however, it is completely removed from the screen. Only after I select a new company from my DropDownList will a record re-display in the FormView.
Does anyone have an idea as to what may be the issue here?
You need to databind again.
void FormView_ItemInserted(Object sender, FormViewInsertedEventArgs e)
{
Gridview.Databind();
}
You need to trigger the child control to be databound when the parent control has been modified.
I've found that the most reliable palce to do this is in the parent control's DataBound event. After a successful edit, this event is called, because the control needs to re-bind to the edited data.
Here's a snippet from some actual code of mine where I do something similar. In it, I have a control called QuestionGroupResutls that has child records in a control called QuestionResults.
void QuestionGroupResults_DataBound(object sender, EventArgs e)
{
QuestionGroupsEditingDetailsView1.DataBind();
QuestionResults.DataBind();
}
I have this in Page_Load, but you can specify this declaratively in the asmx (I just don't have a code sample).
QuestionGroupResults.DataBound += new EventHandler(QuestionGroupResults_DataBound);
I don't know the name of your controls, but you should be able to do the same thing with yours.

How to disable auto data bind of ASP.NET page?

How can I prevent ASP.NET page from automatically binding data controls on the page? I want to increase performance and I want to do binding of each data control based on my own order.
Simple, don't setup data binding on the controls in the designer.
You would then have to bind the controls inside the code behind part of the page with code.
Not quite what the OP asked for but it is also possible to cancel the Select operation on the Datasource control by adding an event handler to the Selecting event.
public void DataSource_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
if (CancelSelect())
{
e.Cancel=true;
return;
}
}

Getting data from child controls loaded programmatically

I've created 2 controls to manipulate a data object: 1 for viewing and another for editing.
On one page I load the "view" UserControl and pass data to it this way:
ViewControl control = (ViewControl)LoadControl("ViewControl.ascx");
control.dataToView = dataObject;
this.container.Controls.Add(control);
That's all fine and inside the control I can grab that data and display it.
Now I'm trying to follow a similar approach for editing. I have a different User Control for this (with some textboxes for editing) to which I pass the original data the same way I did for the view:
EditControl control = (EditControl)LoadControl("EditControl.ascx");
control.dataToEdit = dataObject;
this.container.Controls.Add(control);
Which also works fine.
The problem now is getting to this data. When the user clicks a button I need to fetch the data that was edited and do stuff with it.
What's happening is that because the controls are being added programmatically, the data that the user changed doesn't seem to be accessible anywhere.
Is there a solution for this? Or is this way of trying to keep things separated and possibly re-usable not possible?
Thanks in advance.
Just keep a reference to the control as a variable in the page's code-behind. I.e.
private EditControl control;
protected void Page_Init(object sender, EventArgs e)
{
control = (EditControl)LoadControl("EditControl.ascx");
control.dataToEdit = dataObject;
this.container.Controls.Add(control);
}
protected void Button_Click(object sender, EventArgs e)
{
var dataToEdit = control.dataToEdit;
}
As long as you're creating the control in the right part of the page's lifecycle (Initialization) then ViewState will be maintained. I'm assuming dataToEdit is just a TextBox or something?
Controls created dynamically must be added on Init or PreInit event on the page.
You have to do it here because controls state is not yet loaded. If you add the the control AFTER you'll have them empty since the page already filled control page values early in the page life cycle.
More info about page life cycle here
Here's my solution:
In the page, I keep a reference to the control that is loaded programmatically.
In the control I created a GetData() method that returns an object with the data entered by the user.
When the user submits the form, the page calls the GetData() method on the control to access the data the user entered.

How do you avoid duplicate items when a databound control gets bound twice?

How do you avoid duplicate bound items in this scenario:
There's a databound control on a page (a DropDownList in this case, though I don't think it matters). It has AppendDataBoundItems set to "true". Somewhere in the code, a DataSource is set and DataBind is called. So this control is bound explicitly.
You have a bunch of other things to bind on the page, so you call Page.DataBind.
Your databound control now has duplicate items in it. It was (1) bound explicitly, then (2) Page.DataBind bound it again. Since AppendDataBoundItems was true, the second bind appends to the first, and you end up with double the items.
A couple limitations:
The explicit call to DataBind on the control is done through some centralized code, and would be painful to change.
I really need to bind the rest of the page in aggregate (via Page.Databind()) because there's too many other databound elements to do it individually without writing a ton of individual calls.
I need a method like... Page.DataBindExceptIfTheyHaveAlreadyBeenBoundDuh()
Turn off the AppendDataBoundItems after you do the Control.DataBind(). Then you Page.DataBind() won't append the items again.
DropDownList.DataSource = Data;
DropDownList.DataBind();
DropDownList.AppendDataBoundItems = false;
The bottom line is that there's no great solution. You need to architect your page so that they don't bind controls twice, which means re-writing parts of the page if necessary. The pain of this is better than the workarounds.
You can set AppendDataBoundItems="False" to the DropDownList and in the DataBound event you can add and select a new listitem like here:
protected void ddlNeighborhoods_DataBound(object sender, EventArgs e)
{
ListItem li = new ListItem("- Select -", "-1", true);
li.Selected = true;
ddlCities.Items.Insert(0, li);
}
I have come across this issue many times in the past and the best solution that I have found that works in pretty much all the cases that I had; was to use a UNION select -1 as Value, '- Select -' as Text.
This worked even when you had grid within a grid and databound to a dropdown that was in a usercontrol within that inner grid.
Using code-behind to load the grid will not allow databinding to a usercontrol field.
I hope this tip helps...
Usually this happens in legacy code when you don't want to make too many changes that would break the rest of the page/control. In some cases with a dropdownlist you may have to clear out the items in the dropdownlist.databinding event as a quick fix.
protected void DropDownList1_DataBinding(object sender, EventArgs e)
{
if((sender as DropDownList).Items.Count > 0)
{
(sender as DropDownList).Items.Clear();
}
}
note: You should be careful doing this if the items values change.
I've faced this in asp.net retrieving values from mysql database. On autopostback the values were being added to the already existing values in the dropdownlist.
solution:
i had an sqlcommand to first count the number of rows concerned in the database table. And stored the value in Intvariable1
Then declared another intVariable. had
session("intvariable")=Dropdownlist1.items.count
while session("intvariable") > session("intvariable1")
Dropdownlist1.items.removeAt(Session("intvariable")-1)
session("intvariable)-=1
End while
'this worked for me

Resources