UpdatePanel or RadAjaxPanel in RadGrid EditForm template not working - c#

I have a RadGrid in which I'm using an EditForm FormTemplate.
Inside of this there's a list (RadComboBox) with some companies. When a user selects one of these companies, it should fill another RadComboBox with a list of all locations.
At first I tried this using an UpdatePanel, then a RadAjaxPanel. Neither work.
This is a stripped down version:
<FormTemplate>
<table>
<telerik:RadAjaxPanel runat="server">
<tr>
<td>
Company
</td>
<td>
<telerik:RadComboBox ID="rcbCompany" runat="server" Width="250px" ValidationGroup="NewResource"
DataTextField="C_Name" DataValueField="Bedrijf_ID" AppendDataBoundItems="true"
OnSelectedIndexChanged="rcbCompany_OnSelectedIndexChanged">
</telerik:RadComboBox>
</td>
</tr>
<tr>
<td>
Locatie
</td>
<td>
<telerik:RadComboBox ID="rcbLocation" runat="server" Width="250px" ValidationGroup="NewResource"
DataTextField="location" DataValueField="Location_ID" AppendDataBoundItems="true" />
</td>
</tr>
</telerik:RadAjaxPanel>
</table>
</FormTemplate>
How can you make this work? If it's impossible, please give alternative approaches that don't require much work.

You can do it using ItemDataBound event on grid, i have shown the example to bind country drpdown:
protected void gridLocation_ItemDataBound(object sender, GridItemEventArgs e)
{
if (e.Item.IsInEditMode)
{
GridEditableItem item = (GridEditableItem)e.Item;
if (!(e.Item is IGridEditableColumn))
{
RadComboBox combo = (RadComboBox)item.FindControl("dropdwnCountry");
LoadCountries(combo);
}
}
}
protected void LoadCountries(RadComboBox combo)
{
//your defn goes here
}
And to cascade drop down you can take the onchange event event of country like:
protected void country_selected(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
RadComboBox combo = (RadComboBox)sender;
GridEditableItem edit = (sender as RadComboBox).NamingContainer as GridEditableItem;
RadComboBox combos = (RadComboBox)edit.FindControl("dropdwnState");
LoadStates(combos, combo.SelectedValue);
}
protected void LoadStates(RadComboBox combo,string countryId)
{
//your defn goes here
}
Hope this helps.

Related

FindControl() always returns null from DataList Textbox

I have 8 items in a SQL table with a Description, ItemNumber, and ImagePath.
protected void Page_Load(object sender, EventArgs e)
{
//fill the datalist for the Signs Table
string tCallFrom = "Program." + System.Reflection.MethodBase.GetCurrentMethod().Name;
string tQry = #"SELECT * FROM [js_Signs]";
DataTable tblSigns = objCommMethods.fReturnTableFromQry(clsDBSelect.enumDBSelect.ProjectMaster, tQry, tCallFrom);
SignsList.DataSource = tblSigns;
SignsList.DataBind();
}
I am using a DataList to show all of the items along with a textbox that will allow a user to input the number of items they want:
<asp:DataList ID="SignsList" runat="server" RepeatColumns="4" CellPadding="2" Width="90%" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<table>
<tr>
<th>
<%#DataBinder.Eval(Container.DataItem, "Description") %>
</th>
</tr>
<tr>
<th>
<%#DataBinder.Eval(Container.DataItem, "ItemNumber") %>
</th>
</tr>
<tr>
<td>
<asp:Image ID="SignImage" runat="server" ImageUrl='<%#DataBinder.Eval(Container.DataItem, "ImagePath") %>' />
</td>
</tr>
<tr style="text-align: center;">
<td>
<asp:TextBox ID="txtSignQuantity" runat="server" CssClass="txtBox" BackColor="White" Enabled="true"
type="number" min="0" ToolTip="Please choose quantity of signs needed."/>
</td>
</tr>
<tr>
<td>
<p> </p>
</td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
<div class="btnGroup">
<div class="btnDiv">
<asp:Button ID="btnSave" runat="server" Text="Save" CssClass="btnSave" Width="90px" Visible="true" OnClick="btnSave_Click"/>
</div>
<div class="btnDiv">
<asp:Button ID="btnCancel" runat="server" Text="Clear" CssClass="btnCancel" Width="90px" Visible="true" OnClick="btnCancel_Click"/>
</div>
</div>
After the saved button is clicked in C# I want to find out the value that a user entered but it is always returning null:
protected void btnSave_Click(object sender, EventArgs e)
{
TextBox txtSignQuantity;
string tempSignQuantity;
try
{
foreach (DataListItem item in SignsList.Items)
{
txtSignQuantity = item.FindControl("txtSignQuantity") as TextBox;
tempSignQuantity = txtSignQuantity.Text;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
I also checked and the Count of SignsList.Items was 8, so I know that it is retrieving the correct information. Sorry, I've never used a Data List before so I'm not really sure how to go about this...
The short answer is that data binding on postback is causing the problem. Check the Page.IsPostBack property before doing data binding:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//fill the datalist for the Signs Table
string tCallFrom = "Program." + System.Reflection.MethodBase.GetCurrentMethod().Name;
string tQry = #"SELECT * FROM [js_Signs]";
DataTable tblSigns = objCommMethods.fReturnTableFromQry(clsDBSelect.enumDBSelect.ProjectMaster, tQry, tCallFrom);
SignsList.DataSource = tblSigns;
SignsList.DataBind();
}
}
ASP.NET WebForms attempts to abstract away the fact that the control instances that were used to render the page are not the same instances it has when handling postback events. Data binding compounds the abstraction because it has to create controls in response to the DataBind call, and then on postback, recreate them based on the ViewState it saved.
Initializing controls from ViewState happens on the Init event, so when the Load event is fired later in the page lifecycle and you call DataBind on the control, everything it restored gets wiped out and recreated.
As for why you were getting null, it may have been that the controls were wiped out but not recreated; it may have had to do with other event handlers that didn't get rewired after the second data binding.

Update SQL from Checkbox in ListView

Goal: Update row(s) in SQL table when Checkbox inside ListView is clicked.
I would like to update the following columns from sql:
IsApproved
ApprovalType
I am able to find the checkbox in the row that is clicked from the Listview on the page. However, that is as far as I got. Current code below, as well as what I've tried and the subsequent errors.
Code:
aspx:
<asp:ListView ID="lstUsers" runat="server" ItemType="Program.Data.Table" DataKeyNames="ID" SelectMethod="lstUsers_GetData"
OnItemCommand="lstUsers_ItemCommand" DeleteMethod="lstUsers_DeleteItem" OnSorting="lstUsers_Sorting"
OnItemDataBound="lstUsers_ItemDataBound"
ItemPlaceholderID="litPlaceHolder" >
<LayoutTemplate>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>UserName</th>
<th>Approve User</th>
<td><%# Item.LastName %></td>
<td><%# Item.FirstName %></td>
<td><%# Item.UserName %></td>
<td> <asp:CheckBox ID="cbApproved" runat="server" AutoPostBack="true" OnCheckedChanged="Approve_Click" /> </td>
c#:
protected void Approve_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in lstUsers.Items)
{
if ((item.FindControl("cbApproved") as CheckBox).Checked == true)
{
System.Diagnostics.Debug.WriteLine("it was checked!");
I've tried:
item.ColumnName -- but get error ListView does not contain a
definition for ''
item.DataItem -- the output displays what looks
like an object as a whole
(System.Web.UI.WebControls.ListViewDataItem)
item.DataItem.ColumnName
-- but get error Object does not contain a definition for ''
Do the column values im looking to update in SQL have to be displayed on the ASPX page?
I looked through:
https://msdn.microsoft.com/en-us/library/bb398790.aspx#ModifyingDataUsingTheListViewControl
Asp.Net CheckBoxList to update a SqlDataSource
Why not simply cast the sender to a CheckBox?
protected void Approve_Click(object sender, EventArgs e)
{
if ((sender as CheckBox).Checked == true)
{
System.Diagnostics.Debug.WriteLine("it was checked!");
}
}
You must bind data to the ListView inside an IsPostBack check for it to work.
UPDATE
What you want can be done easily with DataKeyNames. Add it to the ListView as a property.
<asp:ListView ID="ListView1" runat="server" DataKeyNames="IDColumn">
Then when the checkbox is changed read the correct key
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack == false)
{
ListView1.DataSource = Common.fillBooks();
ListView1.DataBind();
}
}
protected void Approve_Click(object sender, EventArgs e)
{
//cast the sender back to the checkbox
CheckBox cb = sender as CheckBox;
if (cb.Checked)
{
//get the parent of the parent (itemtemplate > listiew)
ListView lv = cb.Parent.Parent as ListView;
//get the dataitem from the namingcontainer
ListViewDataItem item = cb.NamingContainer as ListViewDataItem;
//get the correct datakey with the index of the dataitem
int ID = Convert.ToInt32(lv.DataKeys[item.DataItemIndex].Values[0]);
//update database here with the ID
}
}
ListView
<asp:ListView ID="ListView1" runat="server" DataKeyNames="id" ItemType="Namespace.Class">
<ItemTemplate>
<div class="table-responsive">
<table class="table">
<tr>
<td>
<asp:CheckBox ID="cbApproved" runat="server" AutoPostBack="true" OnCheckedChanged="Approve_Click" />
</td>
</tr>
</table>
</div>
</ItemTemplate>
</asp:ListView>
This is what is currently working for me. Too long to add in comment or clutter original post:
ASPX:
<ItemTemplate>
<tr>
<td><asp:Label ID="UserNameLabel" runat="server" Text='<%#Eval("UserName") %>' /></td>
<td> <asp:CheckBox ID="Approved" runat="server" AutoPostBack="true" OnCheckedChanged="Approve_Click" /> </td>
</tr>
</ItemTemplate>
Changed the ItemTemplate to use asp Label controls so I could reference them in the code behind:
protected void Approve_Click(object sender, EventArgs e)
{
foreach (ListViewItem item in listUsers.Items)
{
if ((item.FindControl("Approved") as CheckBox).Checked == true)
{
Label myLabel = (Label)item.FindControl("UserNameLabel");
try
{
IQueryable<SUR> user = null;
user = db.SURs.Where(m => !m.IsApproved && m.UserName == myLabel.Text);
if(user != null)
{
db.sp_SUA(user.FirstOrDefault().ID, SessionMgr.CurrentUserID.ToString(), "Manual");
db.SaveChanges();
}
Response.Redirect(Request.RawUrl);
}
catch(Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
}
}
}
Once getting the control that had the username, I check if the DB has a row with the same value
If so, use a stored procedure to update the DB
EDIT:
After refactoring, I was wondering if it would be more efficient to get rid of the foreach loop, and instead use the OnItemCommand property of ListView and set the OnCheckedChanged for the Checkbox to point to the ItemCommand method? My thinking is since I am not looping through each item, would having the array index be better in terms of Big O?
Code would be:
protected void listSTUFF_ItemCommand(object sender, ListViewCommandEventArgs e)
if (int.TryParse(list.DataKeys[e.Item.DisplayIndex].Value.ToString(), out id)) {
var myQuery = db.Table.Where(a=>a.ID == id).FirstOrDefault();
db.StoredProcedure(myQuery.ID)
db.SaveChanges();

accessing objects in listview after buttonclick in listviewitem

I'm trying to setup a usercontrol.
I've setup a usercontrol with a table incl table header. For each row a second usercontrol is issued displaying 1 row of the table. The line-usercontrol is embedded in a listview.
One cell of the listview contains a textbox, another cell contains a Button. The buttons for each row are using the same buttonclick event using a commandargument for finding the pressed button.
Is there somekind of way to get the value entered in the textbox of that specific line?
code header control:
<asp:Panel runat="server" ID="pnlUcHeader">
<table>
<thead>
<tr>
<th>...</th>
...
<th>Textbox Column</th>
<th>Button Column</th>
</tr>
</thead>
<asp:ListView runat="server" ID="lvUcItemsItem" OnItemDataBound="lvUcItems_ItemDataBound">
<ItemTemplate>
<uc1:Items runat="server" ID="ucItems" CssClass="normal" />
</ItemTemplate>
</asp:ListView>
</table>
code Item User control
<tr runat="server" id="serverRow">
<td>
<asp:Literal runat="server" ID="..."></asp:Literal></td>
<td>
<asp:TextBox runat="server" ID="tbItem"></asp:TextBox>
</td>
<td>
<asp:Button runat="server" ID="btnItem" Text="..." OnCommand="btnItem_Click"/>
</td>
code behind Item User control
protected void btnItem_Click(object sender, CommandEventArgs e)
{
var lineID = e.CommandArgument;
//TextBox tb = FindControl("tbAfhaalDatum)
???????
}
Is this possible in code behind or is there an option to use Javascript/Jquery to postback the value?
Kind regards
You have to access your control's NamingContainer to search for your text box:
protected void btnItem_Click(object sender, CommandEventArgs e)
{
var control = (Control)sender;
var container = control.NamingContainer;
var textBox = container.FindControl("tbItem") as TextBox;
if (textBox != null)
{
var lineID = e.CommandArgument;
var text = textBox.Text;
}
}

How to get Value from DropDownList inside a ListView?

I have a DropDownList inside in ListView..
I wanted to get a data when command clicked.
this is my code..
protected void ListView2_ItemCommand(object sender, ListViewCommandEventArgs e){
string shipmethod = ((DropDownList)e.Item.FindControl("ShippingComapnyDDL")).SelectedValue;
}
but it always return null value..
I've googling about 3 hours, and try many function..
but still cant solve this bug..
please help me guys,
UPDATE
here's my aspx page
<asp:DropDownList ID="ShippingComapnyDDL" runat="server" SelectedValue='<%# Eval("ShippingCompany") %>'>
<asp:ListItem Text="" Value=""></asp:ListItem>
<asp:ListItem Text="FedEx" Value="FedEx"></asp:ListItem>
<asp:ListItem Text="UPS" Value="UPS"></asp:ListItem>
<asp:ListItem Text="Other" Value="Other"></asp:ListItem>
</asp:DropDownList>
DO you have headers set?try
if(e.Item.ItemIndex!=-1)
{
string shipmethod = ((DropDownList)e.Item.FindControl("ShippingComapnyDDL")).SelectedValue;
}
if not working then try
string shipmethod = (e.Item.FindControl("ShippingComapnyDDL") as DropDownList).SelectedValue;
Please try
<%#DataBinder.Eval(Container.DataItem,"ShippingCompany")%>
instead of
<%#Eval("ShippingCompany")%>
For more details:
http://aspadvice.com/blogs/joteke/archive/2008/08/24/Is-_2200_Databinding-methods-such-as-Eval_280029002C00_-XPath_280029002C00_-and-Bind_28002900_-can-only-be-used-in-the-context-of-a-databound-control_2E002200_-causing-you-grief_3F00_.aspx
try this:
DropDownList ddl = (DropDownList)e.Item.FindControl("ShippingComapnyDDL");
if (ddl != null)
{
//code here
}
<asp:ListView ID="lvwCoreConfigureData" runat="server" DataKeyNames="Course_Config_Id" OnItemCommand="lvwCore_Config_ItemCommand" OnItemDataBound="lvwCore_Config_ItemDataBound">
<LayoutTemplate>
<table class="table mobile-stacked mb-0">
<thead>
<tr role="row">
<th style="width: 240px">
<asp:Label runat="server" Text="<%$Lang:Resource.Core_Config_Course %>"></asp:Label>
</th>
</tr>
</thead>
<tbody>
<tr runat="server" id="itemPlaceholder" />
</tbody>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr role="row">
<td data-th="Name">
<asp:DropDownList ID="ConfigCourseName" runat="server" AutoPostBack="true" CssClass="form-control" OnSelectedIndexChanged="ConfigCourseName_SelectedIndexChanged"></asp:DropDownList>
</td>
</tr>
</ItemTemplate>
</asp:ListView>
2 . This methos will be provide data binding to dropdown while edit mode
protected void lvwCore_Config_ItemDataBound(Object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
ListViewDataItem dataItem = (ListViewDataItem)e.Item; // load one row item
var CourseId = ((Edulearn.Model.CoreProgramme.CoreProgrammeConfigrationDM)dataItem.DataItem).CourseId; //
DropDownList ConfigCourseName = (e.Item.FindControl("ConfigCourseName") as DropDownList);
ConfigCourseName.DataSource = CoreProgrammeRepository.GetCoreProgrammeCourseList(TimeZoneId, new { Name = "TEST" }); // Get the data to dropdown (all data)
ConfigCourseName.DataTextField = "Name"; // assign here which one need to display
ConfigCourseName.DataValueField = "CourseId"; // assign here which one is the value for database save
ConfigCourseName.DataBind(); // bind the data
ConfigCourseName.SelectedValue = CourseId.ToString(); // Here selected values from database will be added
ConfigCourseName.Items.Insert(0, new ListItem("Please select")); // Default value only for display
}
}

How do I switch visibility of a control in a repeater?

I have a shopping cart that I am developing as a web user control. ucCart.ascx will appear on three different pages and I want the functionality of the cart to alter depending on which page it appears on. When the customer is confirming their order for example, I do not want to the delete cart item buttons or the recalculate cart button to be visible.
Can this be done programmatically in code behind? I'd rather not use JavaScript. I naively tried to use cartDelete.Visible = false; but that's not liked at all!
You need to get a reference to those controls and call set Visible property to false; something like this pseudo code;
ShoppingCartControlVariable.FinControl("idOfTheControlYouWantToHide").Visible=false;
See this documentation
Adding sample code to demonstrate how this is done:
Assuming you have a repeater like this (notice the OnItemCreated handler):
<asp:Repeater ID="myrepeater" runat="server" OnItemCreated="myrepeater_ItemCreated">
<HeaderTemplate>
<table>
<thead>
<th>
Link
</th>
<th>
Button
</th>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:HyperLink ID="link" runat="server" Text='<%#Eval("Text")%>' NavigateUrl='<%#Eval("Url")%>'></asp:HyperLink>
</td>
<td>
<asp:Button ID="btnDelete" runat="server" Text="Delete" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody> </table>
</FooterTemplate>
</asp:Repeater>
You can hide/show elements in the repeater rows as follows:
protected void myrepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item && (boolean_condition_that_on_which_you_will_decide_what_to_show_and_what_to_hide))
{
e.Item.FindControl("link").Visible = false;
}
}
For example, if I want to hide all link elements on every row and just leave the delete buttons, I can do this:
protected void myrepeater_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType==ListItemType.AlternatingItem)
{
e.Item.FindControl("btnDelete").Visible = false;
}
}
And it will produce this:
For reference, the code that I used to populate my repeater was this:
List<CartItem> items = new List<CartItem>();
for (int i = 0; i < 10; i++)
{
CartItem t = new CartItem();
t.Text="Item " +i;
t.Url="http://www."+i+".com";
items.Add(t);
}
myrepeater.DataSource = items;
myrepeater.DataBind();
I think you can make a public function inside this user control named "hide controls" and call this function in the page you want and this function hide the controls or you can make a boolean property in the user control and the page can set it to false and then you can use this flag to hide the controls inside your usercontrol.

Categories