I have an ASP.NET WebForms project that displays data read from a database via a Repeater. The code for the repeater looks like this:
<asp:Repeater ID="repRMAproduct" runat="server">
<ItemTemplate>
<tr>
<td>
<%# Eval("Description") %>
</td>
<td>
<%# Eval("Qty") %>
</td>
<td>
<asp:TextBox ID="tbNewQty" runat="server"></asp:TextBox>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
What I want is for the user to enter a new Quantity only on the rows that he wants to enter. Then, when he clicks the save button, I can read these new Quantities along with their associated Descriptions.
In MVC I should build the URL using jQuery and pass it to the Controller. But in WebForms it seems less intuitive. Where do I go from here?
In your save-button-click event handler you can loop all items and get the TextBox with FindControl:
foreach(RepeaterItem item in repRMAproduct.Items)
{
TextBox tbNewQty = (TextBox) item.FindControl("tbNewQty");
string newQuantity = tbNewQty.Text.Trim();
int quantity;
if(int.TryParse(newQuantity, out quantity))
{
SaveNewRmaQuantity(product, quantity);
};
}
If you'd use a Label for your product-description you can use FindControl("LblDescriptionId") to get it and to pass it's Text to SaveNewRmaQuantity. You can also use invisible controls(Visible=false), f.e. a Label, to store the ProductId.
Related
I have a large table that can have many null, empty or false columns. I only want to show the columns that are worth showing.
Here is a sample of the query and how I am trying to build up the listview:
var query = (from q in db.tblIncidents
where q.Id == searchQuery
select new
{
q.victim,
q.reportedByVictimPostCode
}).ToList();
lst_Results.DataSource = query;
lst_Results.DataBind();
foreach (var colitem in query)
{
if (!colitem.victim == false)
{
** Help required here please **
lst_Results.Items.Add(new ListViewDataItem(0,1));
}
}
I did start off building my list view on the aspx page, but realised that the result would be lots of empty fields and a waste of time for the user seeing nothing if the user hadn't entered any thing.
What I want to do is achieve this but in the code behind by querying if there is a result to display.
<ItemTemplate>
<tr>
<td>Incident Id:</td>
<td>
<asp:Label ID="lbl_CustomerId" runat="server" Text='<%# Eval("Id") %>' />
</td>
</tr>
<tr>
<td>Reported by the Victim:</td>
<td>
<asp:Label ID="lbl_victim" runat="server" Text='<%# Eval("victim") %>' />
</td>
</tr>
</ItemTemplate>
Would I use something like so?
lst_Results.InsertItem.DataItem(colitem.victim);
Which I get the error method delegate or event expected?
Does it know to insert into the listItem template?
I have a layout template with the itemPlaceholder. The listview works ok just want to target it from code behind.
I'd like to have the user click the select button of, lets say, the 250th row of a 400 row gridview. When they click that, then another gridview that's 3x12 appears below that row, then the 150 other rows appear below that. Is this at all possible? I guess I could create a whole other div that'll have three gridviews that output depending on being <= and > the index of the selected row.
It starts as:
Gridview rows 1-400
Then after row 350 is selected is it:
Gridview rows 1-350
Gridview of row 350 info
Gridview rows 351-400.
It's definitely possible, but I would use a ListView or DataList as your parent container instead, because with a GridView, you'll have to put the child list in a column, which will look ugly. This should put you on the right path:
<asp:ListView ID="lstOuterList" runat="server" DataKeyNames="ID, OtherColumn">
<LayoutTemplate>
<table width="100%">
<asp:PlaceHolder runat="server" ID="itemPlaceHolder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><asp:LinkButton ID="LinkButton1" runat="server" Text="Expand" OnCommand="LinkButton1_Command" CommandArgument='<%#Container.DisplayItemIndex%>'></asp:LinkButton></td>
<td><%#Eval("Value")%></td>
<td><%#Eval("OtherValue")%></td>
<td><%#Eval("OtherOtherValue")%></td>
</tr>
<asp:PlaceHolder ID="plcInnerList" runat="server">
<asp:ListView ID="lstInnerList" runat="server" Width="100%">
<LayoutTemplate>
<tr>
<td colspan="4">
<div style="padding:20px;background-color:#fffeee;">
<table width="100%">
<asp:PlaceHolder runat="server" ID="itemPlaceHolder" />
</table>
</div>
</td>
</tr>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><%#Eval("Value")%></td>
<td><%#Eval("OtherValue")%></td>
<td><%#Eval("OtherOtherValue")%></td>
</tr>
</ItemTemplate>
</asp:ListView>
</asp:PlaceHolder>
</ItemTemplate>
</asp:ListView>
And when the user clicks the LinkButton/Button in DataList1, do something like this:
protected void LinkButton1_Command(object sender, CommandEventArgs e)
{
//pass index of item in command argument
var itemIndex = Convert.ToInt32(e.CommandArgument);
//find the pnlChildView control
var innerPlaceHolder = lstOuterList.Items[itemIndex].FindControl("plcInnerList") as PlaceHolder;
if (innerPlaceHolder != null)
{
innerPlaceHolder.Visible = !innerPlaceHolder.Visible;
if (innerPlaceholder.Visible)
{
var innerList = innerPlaceHolder.FindControl("lstInnerList") as ListView;
if (innerList != null)
{
//the id to retrieve data for the inner list
int keyValue = (int)lstOuterList.DataKeys[itemIndex]["ID"];
//bind the list using DataList1 data key value
innerList.DataSource = new DataTable("DataSource"); //your datasource
innerList.DataBind();
}
}
}
}
one way is:
on the rowcommand of the main grid:
create c# code for the grid will be inside GridView grd = new GridView();
bind this instance like any other grid
add on the controls from the main grid current line, should be something like
e.Cells[0].Controls.Add(grd);
I don't have VS here right now but I guess you could get the idea, I use this approach all the time
I have a link button in a repeater with a couple of databound fields. I'm trying to get to where I can set the buttons onClientClick after the databinding however everytime I try to access the link button I keep getting Null returned.
I've looked through every single question involving repeaters and controls here and haven't been able to figure it out.
The .aspx
<asp:Repeater ID="DailyRepeater" OnItemCommand="DailyRepeater_ItemCommand" runat="server">
<HeaderTemplate>
<tr>
<td class="coltitle">
Time
</td>
<td class="coltitle">
Activity
</td>
<td class="coltitle">
Hours
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr class="evenrow">
<td>
<%# Eval("StartTime","{0:HH:mm}") %>-<%# Eval("EndTime","{0:HH:mm}") %>
</td>
<td>
<%# Eval("Description") %>
</td>
<td>
<%# Eval("Hours","{0:0.0}") %>
</td>
<td>
<asp:LinkButton runat="server" CausesValidation="false" ID="editbutton" Text="Edit">Edit</asp:LinkButton>
</td>
</tr>
</ItemTemplate>
The .aspx.cs
protected void DailyRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
LinkButton myButton = (LinkButton)e.Item.FindControl("editbutton");
myButton.OnClientClick = (popupWindow.GetTargetPopupCode("URL");
}
From what I've read, I should have been able to get to the button using the RepeaterItemEventargs. However I can't seem to find it here. The other thing I thought of was that the binding wasn't happening by the time this happened (which made no sense to be as this is a databound event) but for some reason e is coming back e.Item has a dataItem of null and an itemIndex of -1...
I'm just really confused and lost any help would be greatly appreciated.
Thanks!
It sounds like you haven't guarded against the item type. Typically, it fires the header, all the items, and then the footer. You need to do this:
if(e.Item.ItemType == ItemType.Item || e.Item.ItemType == ItemType.AlternatingItem)
{
LinkButton myButton = (LinkButton)e.Item.FindControl("editbutton");
myButton.OnClientClick = (popupWindow.GetTargetPopupCode("URL");
}
Why not setting the property on the sender object, like this:
sender.OnClientClick = //whatever//
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.
I have a sales simulator written in C#. I did not write this however I am currently modifying it to suit different requirements.
It basically displays a list of products from a database, and has a textbox for each product where you can enter in the quantity sold. The quantity sold is calculated based on it's price in the database.
Now it's all working fine, however there is one SMALL issue. When "Buy" is clicked, it returns me back to the list of products which IS correct, however the quantity I have entered for the previous product remains.
I would like to know how to restore the text boxes to their default value when the after the data is submitted to the database.
I always thought the way to do this would be in the .cs code behind file
txtQuantity.Text = "";
However, for some odd reason, txtQuantity will not show up.
Can anyone think of anything I am doing wrong? Here is a snippet of code from the aspx file.
<form id="form1" runat="server">
Date:
<asp:TextBox ID="txtDate" runat="server" />
Retailer:
<asp:DropDownList ID="dlStore" runat="server"
onselectedindexchanged="dlStore_SelectedIndexChanged" />
<asp:ListView ID="lbProducts" runat="server">
<LayoutTemplate>
<layouttemplate>
<table border="1" cellpadding="1" style="width:800px">
<tr style="background-color:#E5E5FE">
<th>ID</th>
<th>ProductCode</th>
<th>Product Title</th>
<th>RRP $</th>
<th>Quantity</th>
<th>Sale Price $</th>
</tr>
<tr id="itemPlaceholder" runat="server"></tr>
</table>
</layouttemplate>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td style="width: 50px;">
<%#Eval("ProductID") %>
</td>
<td>
<%#Eval("ProductCode") %>
</td>
<td>
<%#Eval("ProductTitle") %>
</td>
<td>
<%#Eval("USListPrice") %>
</td>
<td style="width: 50px;">
<asp:TextBox ID="txtQuantity" runat="server" Text="0" />
</td>
<td style="width: 50px;">
<asp:TextBox ID="txtSalePrice" runat="server" Text="0.00" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
<asp:Button ID="btnBuy" Text="Buy These Items" runat="server" OnClick="btnBuy_Click" />
<asp:Button ID="btnClear" Text="Clear Existing Sales" runat="server"
onclick="btnClear_Click" />
</form>
There's a lot going on in the code behind file and I wouldn't expect anyone to go through it, but how I collect the data from txtQuantity is done with the following line of code:
Int32 quantity = Int32.Parse(((TextBox)item.FindControl("txtQuantity")).Text);
So what I want to be able to do is set this textbox either to be empty, or back to zero.
Any help is appreciated, thanks.
Because that txtQuantity control is within a ListView, there could be any number of instances of that control generated. So you can't access all of them through a single variable.
You will need to look through all controls within that ListView (and several levels deep) to find all your txtQuantity controls.
The same of course for the txtSalePrice control.
EDIT
You could find those textboxes with code like (untested)
public IEnumerable<TextBox> FindTextBoxes(Control parent)
{
if (parent == null) yield break;
foreach (Control child in parent.Controls)
{
TextBox tb = child as TextBox;
if (tb != null)
yield return tb; // found one!
else
foreach(TextBox tb in FindTextBoxes(child))
yield return tb; // found it deeper
}
}
and call it like:
foreach(TextBox tb in FindTextBoxes(lbProducts)
{
if (tb.Name == "txtQuantity")
{
// found a quantity
}
else if (tb.Name == "txtSalePrice")
{
// found the salesprice
}
}