How do I switch visibility of a control in a repeater? - c#

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.

Related

Show hide repeater item template field when used with user control in item template

Hi I have a user control inside repater item template .I want to hide the user controls column based on certain values coming in the string.Below are my code
<asp:Repeater runat="server" ID="MyRepeater" OnItemDataBound="MyRepeater_ItemDataBound">
<ItemTemplate>
<uc2:UCToolEventSummary runat="server" ID="UCSummary"
TaskId='<%#Eval("TaskId")%>'
SystemName='<%#Eval("SystemName")%>'
ResourceName='<%#Eval("ToolName")%>'
Requestor='<%#Eval("Requestor")%>'
CategoryName='<%#Eval("CategoryName")%>'
</ItemTemplate>
</asp:Repeater>
I want to hide the columns based on a string list
list<string> columnsHidden = "SystemName,CategoryName"
So systemname and categoryName should be hidden in the user control
I tried below approach in item databound event but could not able to do that
protected void MyRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
List<String> columnsList = new List<String>();
columnsList = "SystemName,CategoryName";
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
var control = e.Item.FindControl("UCSummary");
foreach (String columnName in columnsList)
{
}
}
}
My Usercontrol code is below
<table class="table table-bordered">
<tr class="row">
<td class="col25">
Task Id: <%=TaskId %>
</td>
<td class="col25">
System Name: <%=SystemName %>
</td>
<td class="col25">
Task Status: <%=TaskStatus %>
</td >
<td class="col25">
Requestor: <%=Requestor %>
</td>
<td class="col25">
Request Type: <%=CategoryName %>
</td>
</tr>
</table>
Can anybody help me on this?
Thank you
You have in your markup added some custom attributes with the columns you need. Thus, on item data bound you should be able to grab/get that control, and then hide/show other columns (controls) in that repeater.
And I don't see the need for a for each loop. The item data bound fires ONE time for each row on data bind.
Thus:
var UCToolEventSummary UC = e.Item.FindControl("UCSummary");
if UC.Attributes.item("CategoryName") = "zoo" {
get other controls - hide or show them - use style in place of visible

ASP.NET Button OnClick within Repeater and LoginView

I'm developing a ASP.NET website with a C# backend. I'm having a problem with how to set an onclick event for buttons that are nested inside of both a loginview and a repeater. The code works fine for displaying all of the other data (anonymous view displays only an error message) but right now the buttons just redirect to the same page and remove the repeater and all contents, whereas they're supposed to run a specific delete function. The repeater, as it is right now, uses an alternatingitem template. If I remove the buttons from the nested controls, they work. I've tried this with buttons, linkbuttons, and imagebuttons. I'd rather use the latter, if possible. Is it possible to assign an Onclick to these buttons if they're nested like this? If not, what approach should I use?
<asp:LoginView ID="LoginLinksView" runat="server" EnableViewState="false">
<AnonymousTemplate>
<asp:Label ID="errorlabel" runat="server"></asp:Label>
</AnonymousTemplate>
<LoggedInTemplate>
<asp:Repeater id="Repeater" runat="server" >
<HeaderTemplate>
<table cellspacing="0" cellpadding="0">
<thead></thead>
</HeaderTemplate>
<ItemTemplate>
<tr class="Repeaterrow">
<!--Additional code here-->
<asp:ImageButton ID="delbutton" runat="server" ImageUrl=
"~/Images/delete.png" Onclick="DeleteOnClick"/>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr class="Repeaterrow">
<!--Additional code here-->
<asp:ImageButton ID="delbutton" runat="server" ImageUrl=
"~/Images/delete.png" Onclick="DeleteOnClick"/>
</tr>
</AlternatingItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
</LoggedInTemplate>
</asp:LoginView>
Here are the problems with your approach
1- The button issues postback as it should. But you need to put some CommandArgument with to identify "key" or which row you are processing it for.
2- Re Bind your Repeater with source. Below is the sample code for you.
protected void Page_Load(object sender, EventArgs e)
{
BindRepeater();
}
private void BindRepeater()
{
List<int> items = new List<int>();
for (int i = 0; i < 10; i++)
{
items.Add(i);
}
Repeater.DataSource = items;
Repeater.DataBind();
}
protected void DeleteOnClick(object sender, EventArgs e)
{
ImageButton delbutton = (sender as ImageButton);
//1- call your method with passing in delbutton.CommandArgument - it will give you key/ whatever you like
//2- Rebind the Repeater here and that will bind controls again...
BindRepeater();
}
protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
ImageButton delbutton = (sender as RepeaterItem).FindControl("delbutton") as ImageButton;
if (delbutton != null)
{
delbutton.CommandArgument = (sender as RepeaterItem).ItemIndex.ToString();
}
}
and ASPX Repeater definition would change to
Thanks,
Riz

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;
}
}

Best way to handle table with dynamic columns

I usually deal with Repeater to generate tables in my asp.net pages, but now I need to handle dynamic columns in my table, so I wonder if there is a common approach to solve this issue using web controls.
I've never used GridView, so I don't know if this is better to render tables with dynamic columns? Can you suggest me wich is the more appropriate approach? Is there a way to achieve this using Repeater?
You could a GridView with AutoGenerateColumns set to true. It would inspect and add the columns in your DataSource
<asp:sqldatasource id="CustomersSource"
selectcommand="SELECT CustomerID, CompanyName, FirstName, LastName FROM SalesLT.Customer"
connectionstring="<%$ ConnectionStrings:AWLTConnectionString %>"
runat="server"/>
<asp:gridview id="CustomersGridView"
datasourceid="CustomersSource"
autogeneratecolumns="True"
emptydatatext="No data available."
allowpaging="True"
runat="server" DataKeyNames="CustomerID">
</asp:gridview>
It is very important to know how you want to handle the situation.
Situation 1:
You have an existing table and from time to time you add columns (which is not very practical though) you can straight away go for the GridView and set the AutoGenerateColumns binding property to true.
Situation 2
You can create your own HTmlHelper Class for handling the tables.
For this you can visit the following post:
How to create MVC HtmlHelper table from list of objects
if you are using MVC.
Here's a quick hack to do this if you must use Repeater:
In the .aspx:
<asp:Repeater ID='rptr' runat='server'>
<HeaderTemplate>
<table>
<thead>
<tr>
<th>
Always visible header col
</th>
<th id='thHidable' runat='server' class='hideable'>
Hideable header col
</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
Repeated col
</td>
<td id='tdHideable' runat='server' class='hideable'>
Hideable repeated col
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody></table>
</FooterTemplate>
</asp:Repeater>
In the code behind (assuming C# used):
protected override void Page_Init()
{
this.rptr.ItemDataBound += new RepeaterItemEventHandler(rptr_ItemDataBound);
}
void rptr_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = (RepeaterItem)e.Item;
if (item.ItemType == ListItemType.Header)
{
HtmlTableCell thHidable = (HtmlTableCell)item.FindControl("thHidable");
if (hideCondition)
{
// thHidable.Visible = false; // do not render, not usable by client script (use this approach to prevent data from being sent to client)
thHidable.Style["display"] = "none"; // rendered hidden, can be dynamically shown/hidden by client script
}
}
else if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
HtmlTableCell tdHideable = (HtmlTableCell)item.FindControl("tdHideable");
if (hideCondition)
{
// tdHideable.Visible = false; // do not render, not usable by client script (use this approach to prevent data from being sent to client)
tdHideable.Style["display"] = "none"; // rendered hidden, can be dynamically shown/hidden by client script
}
}
}
(optional) If you want to dynamically show column on client side (assuming it was rendered), using jQuery (for brevity):
$(".hideable").show();

Once clicking the select button of a row, a gridview appears between that row and the rest of the gridview. Possible?

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

Categories