I get the SelectedValue = "" when i click on My button .
My aspx :
<telerik:RadComboBox ID="ddl_contactList" runat="server" AutoPostBack="True" CausesValidation="False"
CollapseDelay="0" Culture="ar-EG" ExpandDelay="0" Filter="StartsWith" ItemsPerRequest="10"
MarkFirstMatch="true" Skin="Outlook" EnableAutomaticLoadOnDemand="True" EmptyMessage="-New Menu-"
ShowMoreResultsBox="True" OnSelectedIndexChanged="ddl_contactList_SelectedIndexChanged"
EnableItemCaching="false" EnableLoadOnDemand="True" EnableVirtualScrolling="True">
</telerik:RadComboBox>
My .cs :
private void BindContactLists(int year, int main_code)
{
ddl_contactList.Items.Clear();
DataTable dt = ContactList.GetContactListsByDep(year, main_code);
ddl_contactList.DataSource = dt;
ddl_contactList.DataTextField = "list_desc";
ddl_contactList.DataValueField = "list_code";
ddl_contactList.DataBind();
}
I call it in the page load because when I call it in the
!Page.Ispostback, I get the following error:
There is no assigned data source. Unable to complete callback request.
How can I fix this problem? Right now:
ddl_contactList.Text == "MySelectedItemText"
but
selectedValue == "" and selectedItem == ""
Move your call to BindContactLists() from the Page_Load() method to the Page_Init() method. This allows the control to be setup for ViewState binding later in the page lifecycle, and allow proper population of the SelectedValue property.
It's normal because you re-bind your datas => so you erase your selected value
I suggest you to set your block in !IsPostBack => you don't erase when you post
In PageLoad
if(! IsPostBack)
{
ddl_contactList.Items.Clear();
DataTable dt = ContactList.GetContactListsByDep(year, main_code);
ddl_contactList.DataSource = dt;
ddl_contactList.DataTextField = "list_desc";
ddl_contactList.DataValueField = "list_code";
ddl_contactList.DataBind();
}
And you persist your control with ViewState
Set EnableViewState="true"
make sure your datasource like dataset or datatable fill when page load or init fire
Related
I'm adding some fields to a gridview dynamically in the gv.DataBinding event. I'm handling the selecting, paging and sorting in C#. Everything renders properly on screen and I can see the data is loaded into the gridview.
<asp:GridView ID="gvPulledBills" runat="server" AutoGenerateColumns="false"
OnDataBinding="gvPulledBills_DataBinding" OnRowDataBound="gvPulledBills_RowDataBound"
OnSelectedIndexChanged="gvPulledBills_SelectedIndexChanged"
AllowSorting="true" OnSorting="gvPulledBills_Sorting"
AllowPaging="true" PageSize="30" OnPageIndexChanging="gvPulledBills_PageIndexChanging"
DataKeyNames="Id" SkinID="gridviewGray">
In the gv.SelectedIndexChanged event, I need to retrieve the Id of the row selected. Id is stored in a HiddenField and the gv.DataKeyNames value is set to ID so I have two ways to retrieve it.
gv.SelectedValue works fine after the initial render. However, when selecting a row after paging/sorting, the gv.SelectedValue returns null. It behaves as if nothing was selected at all, even though my selected row markup is working correctly. Any suggestions on what I need to do to ensure the datakey is retrievable when binding columns dynamically?
Alternatively, I've tried accessing the hidden field directly rather than depending on the gv.SelectedValue...
protected void gvPulledBills_SelectedIndexChanged(object sender, EventArgs e)
{
GridView gv = (GridView)sender;
//var key = (int)gv.SelectedValue;
var index = gv.SelectedIndex - (gv.PageIndex * gv.PageSize);
var row = gv.Rows[index];
var hiddenField = (HiddenField)row.FindControl("hdnId");
var key = int.Parse(hiddenField.Value);
...
}
but the controls collections are empty in every cell, even for explicitly declared fields, even though there is data on the screen.
Explicit declaration
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:HiddenField ID="hdnId" runat="server" Value='<%# Eval("Id") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
Dynamic declaration
private TemplateField CreateTemplateField()
{
var controls = new List<Control>
{
{ CreateHiddenIdField() }
};
var tf = GridViewTools.CreateTemplateField(string.Empty, string.Empty, controls);
tf.ItemStyle.CssClass = "noRightBorder";
tf.HeaderStyle.CssClass = "noBorder";
return tf;
}
private static Control CreateHiddenIdField()
{
var hdn = new HiddenField();
hdn.ID = "hdnId";
hdn.Value = "'<%# Eval(\"Id\") %>'";
return hdn;
}
//in static class GridViewTools
public static TemplateField CreateTemplateField(string headerText, string sortExpression, List<Control> controls)
{
TemplateField tf = new TemplateField();
tf.HeaderText = headerText;
tf.SortExpression = sortExpression;
tf.ItemTemplate = new GridViewTemplate(DataControlRowType.DataRow, controls);
return tf;
}
//... snippet that adds column to grid
var addColumns = new List<DataControlField>();
addColumns.Add(CreateTemplateField());
// add other columns
foreach (var column in addColumns)
{
gv.Columns.Add(column);
}
//...
Does anyone have any suggestions on how to get the SelectedValue populated when using code behind paging/sorting with dynamic columns? Or any suggestions on how to ensure the dynamically created field controls are populated and accessible in code behind?
I have many more columns added, mostly bound fields. I'm doing this to customize the column set based on drop-down fields elsewhere on the page. It's around 30 columns total and I would prefer not to add them all to the gridview, rather than just setting visibility on them all.
UPDATE SOLUTION
The final solution for this was:
var gv = (GridView)sender;
var rowIndex = gv.SelectedIndex - (gv.PageIndex * gv.PageSize);
var key = (int)gv.DataKeys[rowIndex]["Id"];
DisplayWorkDetail(key);
SelectedRow and SelectedValue are null at this point. Only SelectedIndex is populated. By converting the SelectedIndex to a RowIndex, I was able to retrieve the DataKey directly from the row.
I chose to use sender to make the code generic so I can easily extract it to a method for use with other GridViews.
I don't think you can use sender here.
but, while the Rowcommand has NOT changed the selected index, in that index changed event, it HAS changed. So, you can directly use/reference the control
eg:
GridViewRow myGv As GridViewRow = gvPulledBills.SelectedRow
and then:
myGv.RowIndex (get/use row index).
But, you already have the row, so:
hiddenField myField = (HiddenField)myGv.FindControl("hdnId");
int MyKey = int.Parse(myField.Value);
You can also I suppose use the Datakeys collection and not even have that hidden field.
So, you could do this:
GridViewRow myGv As GridViewRow = gvPulledBills.SelectedRow
int RowPK = (int)(gvPulledBills.DataKeys[myGv.RowIndex]["ID"]);
Background
I have a User Control (an .ascx file) which is being dynamically inserting into an asp:PlaceHolder control on a page. That User Control contains an asp:Repeater, which I'm binding to a DataTable.
Theoretically, on the User Control's first load the DataTable is initialized and 3 empty rows are added. A button on the User Control adds additional empty rows to the Repeater, one at a time.
Problem
The issue is that after any PostBack event on the page (namely the button in this example being clicked), the DataTable for the Repeater is empty.
User Control (.ascx)
(simplified)
<asp:TextBox ID="controlOutsideRepeater" runat="server" />
<asp:Repeater ID="myRepeater" runat="server">
<ItemTemplate>
<p><asp:Textbox ID="firstControlInRepeater" runat="server" text='<%# DataBinder.Eval(Container.DataItem, "A") %>' /></p>
<p><asp:Textbox ID="secondControlInRepeater" runat="server" text='<%# DataBinder.Eval(Container.DataItem, "B") %>' /></p>
</ItemTemplate>
</asp:Repeater>
<asp:LinkButton ID="addItemButton" runat="server" Text="Add Item" onclick="addNewItem" />
Code Behind (.ascx.cs)
(also simplified)
public DataTable items {
get {
object i = ViewState["items"];
if (i == null) {
DataTable t = new DataTable();
t.Columns.Add("A");
t.Columns.Add("B");
// add 3 blank items/rows:
t.Rows.Add(t.NewRow());
t.Rows.Add(t.NewRow());
t.Rows.Add(t.NewRow());
ViewState["items"] = t;
return t;
} else {
return (DataTable)i;
}
set { ViewState["items"] = value; }
}
protected void Page_Init(object sender, EventArgs e) {
myRepeater.DataSource = this.items;
myRepeater.DataBind();
}
public void addNewItem(object sender, EventArgs e) {
DataRow r = this.items.NewRow();
this.items.Rows.Add(r);
myRepeater.DataBind();
}
Behavior
The first time the UserControl is loaded, the Repeater contains 3 empty items: good! However, after entering some text in the textboxes both inside and outside the repeater and clicking the "Add Item" LinkButton, the page does a refresh/postback and shows 4 empty items, however the textbox -outside- the Repeater retains it's text. Clicking the "Add Item" LinkButton again also performs a postback and still shows 4 empty items, yet the TextBox outside the Repeater again retains it's text.
My Crazy Guess
I've tried wrapping the Repeater databinding in a (!Page.IsPostBack), but this prevented the Repeater from -ever- being bound, as the UserControl is only programmatically added to the page after a PostBack (a button on the Page adds the UserControl on a click, and then the Page checks each PostBack to see if there should be a user control present and re-adds it to the Page if needed). So I'm guessing there's a problem with the Page re-creating the User Control on every PostBack, but can't explain why the TextBox outside the Repeater would retain it's value, and why the ViewState doesn't seem to remember my item (on each postback ViewState["items"] is null and gets re-built within the getter).
HELP!
The problem is you are data binding every single request when really you only want to data bind on the first request. Since you don't data bind on the first page load, you will have to check if you are data bound in a way other than !Page.IsPostBack. You could add a property to your user control to handle this and then check against that every page load / page init.
Update: With more details from comments
I see your AddItem() now. I've had problems using viewstate this way though I'm not entirely sure why. I've had to do it more like the following:
public void addNewItem(object sender, EventArgs e) {
DataTable theItems = this.items;
DataRow r = theItems.NewRow()
theItems.Rows.Add(r);
this.items = theItems
myRepeater.DataBind(); //I'm not sure if this belongs here because of the reasons said before
}
Hi I need to access the contents of a textbox that is inside a details view:
<asp:TemplateField HeaderText="Transaction Name:" >
<InsertItemTemplate>
<asp:TextBox ID="txtTransactionName" runat="server" />
</InsertItemTemplate>
</asp:TemplateField>
Tried string v = ((TextBox)detailsNew.FindControl("txtTransactionName")).Text; but it returned "" when I checked.
EDIT: I'm trying the above in detailsNew_ItemInserting(...)
You could try like...
protected void detailsNew_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
string v = ((TextBox)((DetailsView)sender).FindControl("txtTransactionName")).Text;
}
First this Item template control have to be binded with a property from your data source so that when the item inserting event is fire you can access it's data using this code
e.Values["ColumnName"]
Found the problem. Leaving this here to help someone else who might have the same problem.
I cannot use the sender object to get the DetailsView.
So the correct way:
TextBox txt = (TextBox)DETAILSVIEW_ID.FindControl("TEXTBOX_ID") as TextBox;
string tmp = txt.Text;
DETAILSVIEW_IDis the ID of the DetailsView and TEXTBOX_ID the ID of the TextBox crated inside the DetailsView.
I am using a code behind function to bind my dropdownlist dynamically, when a user changes the dropdownlist and submit a purchase, the selectedvalue is always empty.
I have tried both ddl.SelectedItem.ToString(); and ddl.SelectedValue.ToString(); but none work. Also for these 2 code behind functions below, I can't seem to use void methods instead of a function that needs a returning value and a parameter, is there anyway to use void methods without parameters? Any advice is appreciated.
Thanks.
<%# FormattedSize((string)Eval("Size")) %>
<%# FormattedGetSize((string)Eval("Size")) %>
inline:
<asp:DropDownList ID="DropDownList1" runat="server" OnDataBinding='<%# FormattedSize((string)Eval("Size")) %>'></asp:DropDownList>
<a href='AddToCart.aspx?CategoryId=<%# Eval("CategoryId") %>&&ProductId=<%# Eval("ProductId" ) %>&&Size=<%# FormattedGetSize((string)Eval("Size")) %>' style="border: 0 none white;">
Code Behind:
protected string FormattedSize(string size)
{
if (size.Contains("s"))
{
DropDownList ddl = (DropDownList)FormView_Product.Row.Cells[0].FindControl("DropDownList1");
ddl.Items.Add("S");
}
if (size.Contains("m"))
{
DropDownList ddl = (DropDownList)FormView_Product.Row.Cells[0].FindControl("DropDownList1");
ddl.Items.Add("M");
}
if (size.Contains("f"))
{
DropDownList ddl = (DropDownList)FormView_Product.Row.Cells[0].FindControl("DropDownList1");
ddl.Items.Add("Freesize");
}
return null;
}
protected string FormattedGetSize(String Size)
{
DropDownList ddl = (DropDownList)FormView_Product.Row.Cells[0].FindControl("DropDownList1");
string selectedSize = ddl.SelectedItem.ToString();
return selectedSize;
}
The reason why it doesn't work is because.. "you're doing it wrong". You're expecting that the <a href=.. will change based on the user interaction but instead it is already generated when user receives the page. If you want the link to change based on the dropdown, you'd have to have either:
a postback on dropdown selection, then the link would change...
you could change the href with some javascript by attaching event on dropdown selection
What you do in your Page_Load method? Do you check to see if the current request is a post back or not (using IsPostBack)?
If so, check for IsPostBack and bind your DropDownList to the underlying data source only on Get requests.
In the following code everytime its taking only one item from dropdownlist. When I select any other item from dropdownlist its same as first item.
Please give solution
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
DataSet _subcat = new DataSet();
_subcat = serviceus.Get_SERVICEUS_SUB_CATEGORYLIST(DropDownList1.SelectedValue.ToString());
lbsubcategory.DataSource = _subcat.Tables[0].DefaultView;
lbsubcategory.DataTextField = Convert.ToString(_subcat.Tables[0].Columns["CATEGORY_SUB1_NAME"].ColumnName);
lbsubcategory.DataBind();
Label5.Visible = true;
}
Check how you bind your dropdownlist. I think you're binding it everytime your page posts back to server. Try to use IsPostBack property of the page :
if (!IsPostBack){
DropDownList1.DataSource = datasource;
DropDownList1.DataBind();
}
Do you have:
if(!IsPostBack) {
DataBind();
}
around your initial databind (eg in OnLoad)
EnableViewState="False" on the lbsubcategory.
Assuming AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged"