Child UserControl missing datasource when binding through ListView - asp.net

I have a UserControl that takes a class object as property "DataSource." On DataBind, I apply properties of that object to controls -- TextBox, RadioButton, etc -- inside the UserControl.
This works great when I just set the UC on a page, bind, and go.
Now, I'm attempting to use this control in the ItemTemplate of a ListView like so;
<ItemTemplate><uc1:MyItem ID="MyItem1" runat="server" DataSource='<%# Container.DataItem %>' /></ItemTemplate>
and bind to an array of those objects. The array is populated but I'm reaching my DataBind method of the UC with DataSource = null. Am I missing something?
EDIT: Holidays kept me away from this.
So, apparently I was calling base.DataBind() too late. My LoadForm(DataSource) method to load the object into the form fields preceded base.DataBind(). Swapping them fixed allowed me access to DataSource with no problem.
public override void DataBind()
{
base.DataBind();
LoadForm(DataSource);
}
Am I understanding my problem right? Was I just doing things out of order?

The "<%# %>" syntax tells the compiler to run the associated code during the control's DataBinding event -- but DataSource needs to be set before the DataBinding event to be effective.
One way to work around the issue might be to do your binding-related processing after the DataBind event runs, such as in PreRender.

You just have to know that you might be reloading the page, and you may try to use the
if(!IsPostBack)
in your Page_Load(object sender, EventArgs e)

Related

Is there any real difference between assigning an event handler in ascx vs codebehind?

Is there any behavioral difference between:
<asp:Repeater ID="myRepeater" runat="server" OnItemDataBound="myRepeater_ItemDataBound">
</asp:Repeater>
vs:
protected void Page_Load(object sender, EventArgs e)
{
myRepeater.ItemDataBound += new RepeaterItemEventHandler(myRepeater_ItemDataBound);
}
No, there is no difference in execution, because in reality, when you assign it in the ascx, it's actually written to a code behind "behind the scenes" in the .designer.cs file (assuming you're using the designer) or in a compiled temp file (if using background compile).
They both do the same thing. But the aspx version can be handled by the GUI designer.
According to Page Life cycle there is no difference between assigning an event handler in ascx and codebehind.
Page_Init of a page raise after all controls have been initialized. so user control is also a control for the page.
have look on this ASP.NET Page Life Cycle on MSDN for detailed information.
you can use private methods if you assign it on the code behind. you can't assign private methods in aspx/ascx. that's a difference came to my mind.

Dynamic dropdownlist in repeater, ASP.NET

Basically, the codes I have is from here : http://ranafaisal.wordpress.com/2009/02/17/dynamically-adding-removing-textboxes-in-aspnet-repeater/
However, the thing is that, I will need a dropdownlist with textboxes. The purpose of having dropdownlist is to allow users to select their country of origin. They have the option to Add or Remove the particulars they have entered before.
This is my error message:
'ddlName' has a SelectedValue which is
invalid because it does not exist in
the list of items. Parameter name:
value
This is my dropdownlist code inside a repeater in Default.aspx
<asp:DropDownList ID="ddlName" runat="server" SelectedValue='<%# DataBinder.Eval(Container.DataItem, "ddl") %>'></asp:DropDownList>
The codes behind is exactly the same as the link I provided.
Points to note: There is no database involved.
Please not tell me to google or anything because I have been googling for the past few hours, to no avail. I definitely have googled enough, and tried the solutions given by others before posting here. I am pretty much at my wits end
To add-on, I cannot even start-up my application because of the dropdownlist problem.
The problem is you need to fill the DropDownList possible options before you set the selected value which you are trying to do inline with the Eval. I would switch it to use the OnDataBinding of the DropDownList and do what you need there.
Example:
<asp:DropDownList ID="ddlName" runat="server" OnDataBinding="ddlName_DataBinding" />
protected void ddlName_DataBinding(object sender, System.EventArgs e)
{
DropDownList ddl = (DropDownList)(sender);
// Fill your ddl here (eg. ddl.Items.Add("abc", xyz");
// Make sure the value you are going to set the selected item to has been added
// Now set the selected value since it will now exist.
ddl.SelectedValue = Eval("ddl").ToString();
}

GridView: Why do I STILL have to do my own Sorting and Paging?

When I already enabled paging and sorting for a GridView Control?
Here's my aspx code:
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True">
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:plantsSQLConnectionString %>"
SelectCommand="SELECT * FROM [Plants]"></asp:SqlDataSource>
I do the query and DataBind in Page_Load() and the data were displayed properly. I was expecting GridView to handle the paging and sorting for me but when I tried to page or sort, the page crashed and I was told to provide the Sorting and PageIndexChanging handlers.
What did I do wrong? Thanks.
Here's my code behind. You can assume GetData works because I see the records displayed properly.
protected void Page_Load(object sender, EventArgs e)
{
// Declare the query string.
String queryString = "Select * from plants";
// Run the query and bind the resulting DataSet
// to the GridView control.
DataSet ds = GetData(queryString);
if (ds.Tables.Count > 0)
{
GridView1.DataSource = ds;
GridView1.DataBind();
}
}
Additional details: If I don't do code behind and do the query in the aspx file then GridView can sort and page automatically. [Meaning I used the wizard and connected the GridView to the datasource in the aspx file resulting in a DataSource ID being associated with the GridView control.] How can it do the paging and sorting in this case and not when code is moved to PageLoad? Thanks for any insight.
The GridView does yet not know how to sort if the user clicks on a column. Therefore you need to provide the SortExpression for the sortable columns.
Also you might want to provide extra functionality to sort ascending/descending if user clicked on the same column twice. Therefore you need to store the current SortExpression+SortDirection somewhere f.e. in ViewState.
Some considerations why and when sorting might not be working automatically:
When a data source control that
supports sorting is bound to the
GridView control, the GridView control
can take advantage of the data source
control's capabilities and provide
automatic sorting functionality. When
the GridView control is bound to a
data source by setting the DataSource
property programmatically, you must
provide the sorting functionality by
using the Sorting event.
Here are further informations on Sorting:
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.allowsorting.aspx
Some considerations why and when paging might not be working automatically:
If the data source does not support
paging directly and does not implement
the ICollection interface, the
GridView control cannot page. For
example, if you are using a
SqlDataSource control and have set its
DataSourceMode property to DataReader,
the GridView control cannot implement
paging.
Here are more informations on why the GridView might not support paging directly:
http://msdn.microsoft.com/en-us/library/5aw1xfh3.aspx
Edit: Remember to check for ! Page.IsPostback in Page_Load before you databind the GridView! Otherwise the GridView will get the old data/paging/sorting etc. on postbacks.

How to include Session variable in NavigateUrl in hyperlink

I'm sure I've done this before, but can't remember the syntax. How do I include a session variable in nagivateUrl in a hyperlink?
I've tried this:
<asp:HyperLink ID="lnkMyLink" runat="server" Text="My Link"
NavigateUrl='<%# "http://absoluteURL.org?param=" +
Session["myParameterValue"].ToString()%>'></asp:HyperLink>
and this:
<asp:HyperLink ID="lnkMyLink" runat="server" Text="My Link"
NavigateUrl='<%# String.Format("http://absoluteURL.org?param={0}",
Session["myParameterValue"].ToString()) %>'></asp:HyperLink>
Because you've used the data binding format (<%#), you need to call the HyperLinks .DataBind() method from your codebehind.
You need your Page_Load method to look something like this:
protected void Page_Load(object sender, EventArgs e)
{
lnkMyLink.DataBind();
}
The only thing to bear in mind that using Data Binding for something like this, i.e. not specifically Data Binding, may be a bit confusing for anyone who has to maintain your code in the future. Whilst it'll be fairly quick and easy to determine what you've done and why you've done it, anything that can cause future confusion should be removed from your code where posible. Therefore a potentially better option would be to put the following in your Page_Load:
lnkMyLink.NavigateUrl =
string.Format("http://absoluteURL.org?param={0}", Session["myParameterValue"]);
If your link is not in a data-bound control, such as a ListView, you can still force databinding (per your first code snippet) by calling .DataBind() on the control from code-behind.

How do I add an empty first entry do an <asp:DropDownList>?

I have a dropdown, I have a datasource, I have AutoPostBack set to true.
I want to add a first entry to the datasource that says something like "--- select country ---" and selecting this entry won't cause postback.
This feels like it should be easy to do, yet I can't seem to be able to find a good solution.
Thanks.
In your aspx page (the important part is handling the DataBound event and setting CausesValidation="true" to force validation of a drop down list):
<asp:DropDownList ID="ddlCountries" runat="server" DataSourceID="dsCountries" AutoPostBack="true" OnDataBound="ddlCountries_DataBound" CausesValidation="true" />
<asp:RequiredFieldValidator ID="rfvCountries" runat="server" ControlToValidate="ddlCountries" Display="Dynamic" ErrorMessage="Please select a country." />
In your codebehind (it is important that the value of the inserted item is String.Empty for the required field validator to work!):
protected void ddlCountries_DataBound(Object sender, EventArgs e)
{
ddlCountries.Items.Insert(0, new ListItem("--- select country ---", String.Empty));
}
Note: If you don't want the validator's message to display, set the "Display" property to "None".
You can also add the row manually through the designer but you have to make sure that the DropDownList's property AppendDataBoundItems = True as well so that the databound rows are tacked onto the first row.
Previous answers deal with inserting the value, but I understand your problem is the AutoPostBack property. I suppose you dont want to postback that value and that's your problem, am I right?
Maybe there's a better solution, but I'd suggest not using AutoPostBack. You could handle postback automatically using the selected value change event.
IMHO if the AutoPostBack does not work as you want, it's always better to implement your own solution that to put some kind of "patch" over it to "fix" it.
Hope that helps
Use the insert method as others have suggested to add the item at index 0 with a value to indicate not selected ( for example 'unknown'). Then use validators, add a required field validator and set the InitialValue property to the value of the new list item ('unknown' in our example).
Set index 0 to be the selected item on page load and if not postback.
If the user doesn't select another option the validator will prevent the postback.
Hope that's what you are looking for.

Resources