Master/Detail help needed for ASP.NET newbie. (screenshot too) - asp.net

I'm just beinning basic data driven ASP.NET webforms design. I have the first part of a form working, but I don't know what to do next.
Please see this screenshot of what I have created so far: http://www.twitpic.com/2gnmr
I need help knowing what kind of HTML element to use in the master list, and what event/trigger on that element to use to fire off the "get child records for this selected item" sequence?
Also, is a ListView even the correct way to present the master list? At this time, I'm not trying to provide any editing features; I'll get to that later, I guess.
Should I use some other ASP.NET data control rather than hand-coding a listview like I am doing?
I don't want to see an actual "Select" link item beside each Customer Name (that looks goofy). I want the Customer Name to be the link to click on.
So, you can see in my code below that I have a ListView to present a list of CustomersWithOpenOrders. But, it's just a static list, so how do I make the Company Name label clickable, and what else will I need to make it fire back to some code-behind to fetch the child records. I already have a code-behind method to get child records for a passed-in CustomerNumber into a DataTable, and I think I would know how to bind that to a grid or listview for child records, but I do not know how to pass the CustomerNumber from the master ListView to the method from the UI form.
<asp:ListView ID="ListView1" runat="server">
<LayoutTemplate>
<table cellpadding="2" border="0" ID="tbl1" runat="server">
<tr id="Tr1" runat="server" class="lvHeader">
<th id="Th1" runat="server">Customer</th>
</tr>
<tr runat="server" id="itemPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr id="Tr2" runat="server">
<td>
<asp:Label ID="label2" class="FirstLine" runat="server" Text='<%# Eval("company") %>' />
<br />
<div class="SecondLine">
<asp:Label ID="labelCustNo" runat="server" Text='<%# Eval("custno") %>'/>
<asp:Label runat="server" Text='Ph: '></asp:Label>
<asp:Label ID="label3" runat="server" Text='<% # Eval("phone") %>' />
</div>
</td>
</tr>
</ItemTemplate>
</asp:ListView>

I personally haven't found a case where the ListView can't solve my needs. If you want to create a customer selection style list you can use a link button for binding.
<asp:ListView runat="server" id="CustomersList" ItemCommand="CustomersList_ItemCommand">
<LayoutTemplate>
<table cellpadding="2" border="0" ID="tbl1" runat="server">
<tr id="Tr1" runat="server" class="lvHeader">
<th id="Th1" runat="server">Customer</th>
</tr>
<tr runat="server" id="itemPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr id="Tr2" runat="server">
<td>
<asp:LinkButton ID="link1" class="FirstLine" runat="server" Text='<%# Eval("company") %>' CommandName="Select" />
<br />
<div class="SecondLine">
<asp:Label ID="labelCustNo" runat="server" Text='<%# Eval("custno") %>'/>
<asp:Label runat="server" Text='Ph: '></asp:Label>
<asp:Label ID="label3" runat="server" Text='<% # Eval("phone") %>' />
</div>
</td>
</tr>
</ItemTemplate>
</asp:ListView>
<asp:ListView runat="server" ID="OrderList">
<!-- Child Rows implementation -->
</asp:ListView>
Then you would need to bind the event to the ListView.ItemCommand.
protected void CustomersList_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName = "Select")
{
if (e.Item.ItemType != ListViewItemType.DataItem) return;
var dataItem = e.Item as ListViewDataItem;
if (dataItem == null) return;
var customer = dataItem.DataItem as Customer;
if (customer == null) return;
this.OrdersList.DataSource = GetChildRecords(customer.ID);
this.OrdersList.DataBind();
}
}

Related

SortExpression in ASP.NET GridView not working with <HeaderTemplate>

I have an ASP.NET GridView. Now I am adding the SortExpression property tothe <TemplateField> tags, to make specific columns sortable.
Now, one of the columns has some markup content to be added in the header. The problem is, SortExpression does not work if there is a <HeaderTemplate> tag in a <TemplateField>, you have to put it inside the HeaderText property of <TemplateField>. But, all the HTML content does not work properly if I dump it inside the HeaderText property.
<asp:TemplateField SortExpression="FK_TesterID" ItemStyle-Width="300px" FooterStyle-Width="300px" ItemStyle-HorizontalAlign="Center" FooterStyle-HorizontalAlign="Center" HeaderStyle-HorizontalAlign="Center">
<HeaderTemplate>
<table width="100%">
<tr>
<td align="center">
Tester
</td>
</tr>
<tr>
<td>
<asp:DropDownList ID="cmbTestersHeader" ClientIDMode="Static" runat="server" Width="300px" DataSource='<%# PopulateTesterNames() %>' DataTextField="FullName" DataValueField = "PK_ID" Visible="false" AutoPostBack="true" OnSelectedIndexChanged="cmbTestersHeader_SelectedIndexChanged" ToolTip="Bulk Assign Testers !" ></asp:DropDownList>
</td>
</tr>
</table>
</HeaderTemplate>
So you can see, if I put the entire <HeaderTemplate> property inside a headertext, it doesn't work.
But I want to have both functionalities. Can anyone help?
Then you need to provide a control in your HeaderTemplate with CommandName="Sort", for example a LinkButton.
<HeaderTemplate>
<table width="100%">
<tr>
<td align="center">
<asp:LinkButton ID="LbSort" runat="server" CommandName="Sort" Text="Sort" />
</td>
</tr>
<tr>
<td>
<asp:DropDownList ID="cmbTestersHeader" ClientIDMode="Static" runat="server" Width="300px"
DataSource='<%# PopulateTesterNames() %>' DataTextField="FullName" DataValueField="PK_ID"
Visible="false" AutoPostBack="true" OnSelectedIndexChanged="cmbTestersHeader_SelectedIndexChanged"
ToolTip="Bulk Assign Testers !">
</asp:DropDownList>
</td>
</tr>
</table>
</HeaderTemplate>
This is a quite old thread I have stumbled over while trying to solve exactly that described problem but the solution provided here didn't worked for me. If you have a Sorting method defined for the GridView then
<asp:LinkButton ID="LbSort" runat="server" CommandName="Sort" Text="Sort" />
will call that method
protected void GridView_Sorting(object sender, GridViewSortEventArgs e)
{
dt.DefaultView.Sort = e.SortExpression;
but e.SortExpression will be null and no sorting is happening. You have to first pass the Column's name through the CommandArgument of the LinkButton. Only then it worked in my case!
<asp:LinkButton ID="LbSort" runat="server" CommandName="Sort" CommandArgument="ColumnName" Text="Sort" />

Binding a Dictionary to a repeater asp.net 4

i have a dictionary in this form Dictionary<int, List<CartItem>>, this dictionany contain informationa about my shopping cart item. i am looking for a way to display the result in a repeater or a datalist what ever is better. i have started using a repeater and i got stuck
i want to display the information in the list in the repeater for each element in the repeater
in the page.aspx.cs
void bindinfo()
{
ShoppingCart cart = ShoppingCart.GetShoppingCart();
RepeaterCustomerShoppingCarts.DataSource = cart.dictionaryShoppingCart;
RepeaterCustomerShoppingCarts.DataBind();
}
in page.aspx
<asp:Repeater id="RepeaterCustomerShoppingCarts" onitemdatabound="RepeaterCustomerShoppingCarts_ItemDataBound" runat="server">
<HeaderTemplate>
<table width="100%" border="0" cellspacing="0" cellpadding="0" class="shopping-table">
<tr>
<th> </th>
<th>Merchant Name</th>
<th>Quantity</th>
<th>Total Amount</th>
<th> </th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td class="first"><asp:Image ID="MerchantLogo" runat="server" width="52" height="46"/></td>
<td>
<b><asp:Label ID="lblTitle" runat="server" Text=""></asp:Label></b>
<p> <asp:Label ID="lblDetails" runat="server" Text=""></asp:Label> </p>
</td>
<td>
<div class="dropdown">
<asp:Label ID="lblQuantity" runat="server" Text=""></asp:Label>
</div>
</td>
<td><b><asp:Label ID="lblTotalPrice" runat="server" Text=""></asp:Label> </b></td>
<td><asp:HyperLink ID="hlShopDetails" CssClass="remove" runat="server">More Details</asp:HyperLink></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
any help and advice to try to display the information would be great. the purpose of the page is u can have many shopping cart depending on different merchant and u display them here than there is a link called more details it will take you to a specific cart.
thanks
Try this
protected void RepeaterCustomerShoppingCarts_ItemDataBound(Object Sender, RepeaterItemEventArgs e) {
if (e.Item.ItemType == ItemType.AlternatingItem || e.Item.ItemType == ItemType.Item){
// Grab all your controls like this
var lblQuantity = e.Item.FindControl("lblQuantity") as Label;
var NestedRepeater = e.Item.FindControl("NestedRepeater") as Repeater;
// Get the current data
var data = (KeyValuePair<Int32, List<CartItem>>)e.Item.DataItem;
//Bind the values
lblQuantity.Text = data.Value.Count.ToString();
NestedRepeater.DataSource = data.Value;
NestedRepeater.DataBind();
}
}
The markup would look something like this.
<asp:Repeater id="RepeaterCustomerShoppingCarts" onitemdatabound="RepeaterCustomerShoppingCarts_ItemDataBound" runat="server">
<ItemTemplate>
<asp:Label id="lblQuantity" runat="server" />
<asp:Repeater runat="server" id="NestedRepeater">
<ItemTemplate>
<!-- whatever your controls -->
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
The thing here is that you control your layout in the code behind. Grab the necessary controls there and the current data. Then just do your bindings as normally.
Rather than using the normal Eval("ColumnName") on a dictionary you would simply do Eval("value")
You could do something like this.
<asp:Label ID="lblQuantity" runat="server" Text='<%#(Eval("key")=="Quantity" ? Eval("value") : "") %>' />

How display data in a gallery view mode

Is there a way to display gridview as "gallery view" instead of plain "list view". For example like ebay(you can toggle the view 1.list view, 2.gallery view, 3. side by side view). Any asp.net controls or jQuery controls will do the job for me. Please suggest.
One way to accomplish this would be to use the ListView server control to make a template that looks like the "Gallery View" you have in mind.
<asp:ListView runat="server" ID="ListView1"
DataSourceID="SqlDataSource1"
GroupItemCount="5">
<LayoutTemplate>
<table runat="server" id="table1">
<tr runat="server" id="groupPlaceholder">
</tr>
</table>
</LayoutTemplate>
<GroupTemplate>
<tr runat="server" id="tableRow">
<td runat="server" id="itemPlaceholder" />
</tr>
</GroupTemplate>
<ItemTemplate>
<td runat="server">
<%-- Data-bound content. --%>
<asp:Label ID="NameLabel" runat="server"
Text='<%#Eval("Name") %>' />
</td>
</ItemTemplate>
</asp:ListView>

Can't get edit to work on a ListView

I have the following code which I thought would give me the ability to edit a record in my list view but when i click edit i get a postback but am not able to edit anything. Am i doing something wrong?
<asp:ListView ID="lv_Personnel" runat="server" OnItemEditing="lv_Personnel_ItemEditing">
<LayoutTemplate>
<table cellpadding="2" border="1" runat="server" id="tbl_Personnel">
<tr id="headerRow" runat="server">
<th>
</th>
<th>
Level of Staff
</th>
</tr>
<tr runat="server" id="itemPlaceholder" />
<tr runat="server" id="insertPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr runat="server">
<td>
<asp:LinkButton ID="btnEdit" runat="server" Text="Edit" CommandName="Edit" />
</td>
<td>
<%# Eval("LineDescription")%>
</td>
</tr>
</ItemTemplate>
<EditItemTemplate>
<tr runat="server" style="background-color: #ADD8E6">
<td>
</td>
<td>
Level of Staff:
<asp:TextBox ID="tb_LevelOfStaff" runat="server" Text='<%# Eval("LineDescription") %>' />
</td>
</tr>
</EditItemTemplate>
</asp:ListView>
Are you databinding your ListView to anything? If it's not databound, then you're going to have to manually specify the record that you want to edit by handling the ItemEditing event.
protected void MyListView_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListView1.EditIndex = e.NewEditIndex;
// Re-databind here
}
Based on comments, don't databind on every postback unless you have ViewState turned off.
private void Page_Load()
{
if (!IsPostBack)
{
//databind
}
}
It looks like i just needed to add an OnItemEditing event to my ListView declaration and the function to back it up. I've updated my code snippit above to reflect the changes made in the aspx file.

Accessing controls in the edititemtemplate of a listview

I am working with the listview control. By default I am showing the itemtemplate with an edit button. When the edit button is pressed the listview switches to the edititemtemplate. I need to populate one of the controls in the edititemtemplate based on the item being edited - I've tried accessing the control (via FindControl) in the ItemEditing event (and pretty much every other event as well), however the controls just don't seem to exist. I can access controls in the itemtemplate ok, but not the edititemtemplate.
Can anyone let me know how I can access a control held within the edititemtemplate of a listview, and from which event I should do so?
EDIT
I'm trying to access the control using this:
protected void UnitsLV_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListViewItem item = UnitsLV.Items[e.NewEditIndex];
ListBox tempLB = (ListBox)e.item.FindControl("ListBox3");
}
I've also tried in ItemDataBound and ItemCreated.
The listview declaration is:
<asp:Content ID="Content1" ContentPlaceHolderID="ColumnA" runat="server">
<asp:Panel ID="Panel1" runat="server">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Panel ID="SummaryPnl" runat="server">
<asp:ListView ID="UnitsLV" runat="server" DataSourceID="DataLDS" DataKeyNames="u_uid"
InsertItemPosition="LastItem" OnItemInserting="UnitsLV_ItemInserting" OnItemDataBound="UnitsLV_ItemDataBound"
OnItemCreated="UnitsLV_ItemCreated" onitemediting="UnitsLV_ItemEditing">
<ItemTemplate>
<tr class="rowA">
<td>
<asp:Label runat="server" ID="UnitIDLbl" Text='<%# Eval("u_uid")%>'></asp:Label>
</td>
<td>
<%# Eval("u_Title")%>
</td>
<td>
<asp:LinkButton ID="EditBtn" runat="server" CommandName="Edit" CommandArgument='<%#Eval("u_uid") %>'
Text="Edit" />
</td>
<td>
<asp:LinkButton ID="DeleteBtn" runat="server" CommandName="Delete" CommandArgument='<%#Eval("u_uid") %>'
Text="Delete" />
</td>
</tr>
</ItemTemplate>
<InsertItemTemplate>
<tr class="rowB">
<td>
<br />
</td>
<td>
<br />
<asp:TextBox ID="TitleTB" runat="server" Text='<% #Bind("u_Title")%>'></asp:TextBox>
</td>
<td>
<br />
<asp:ListBox ID="ListBox3" runat="server"></asp:ListBox>
<asp:ListBox ID="ToBeDeletedLB" runat="server"></asp:ListBox>
</td>
<td>
<asp:LinkButton ID="InsertBtn" runat="server" CommandName="Insert" Text="Insert" />
</td>
<td>
<asp:LinkButton ID="CancelBtn" runat="server" CommandName="Cancel" Text="Cancel" />
</td>
</tr>
</InsertItemTemplate>
<EditItemTemplate>
<tr class="rowB">
<td>
<br />
<asp:Label runat="server" ID="UnitIDLbl" Text='<%# Bind("u_uid")%>'></asp:Label>
</td>
<td>
<br />
<asp:TextBox ID="TitleTB" runat="server" Text='<% #Bind("u_Title")%>'></asp:TextBox>
</td>
<td>
<br />
<asp:ListBox ID="ListBox3" runat="server"></asp:ListBox>
<asp:ListBox ID="ToBeDeletedLB" runat="server"></asp:ListBox>
</td>
<td>
<asp:LinkButton ID="UpdateBtn" runat="server" CommandName="Update" Text="Update" />
</td>
<td>
<asp:LinkButton ID="LinkButton2" runat="server" CommandName="Cancel" Text="Cancel" />
</td>
</tr>
</EditItemTemplate>
<LayoutTemplate>
<table id="Table2" runat="server" width="100%">
<tr id="Tr1" runat="server">
<td id="Td1" runat="server">
<table id="itemPlaceholderContainer" runat="server" border="0" style="" width="100%">
<tr id="itemPlaceholder" runat="server"></tr>
</table>
</td>
</tr>
<tr id="Tr2" runat="server">
<td id="Td2" runat="server" style=""></td>
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Panel>
</asp:Content>
EDIT:
I've iterated over all the controls in the listview using code similar to below, and the control is still not visible. Does the ItemEditing event fire before the edit template is shown? If so, what event can I use to access the edit template controls?
foreach (Control child in control.Controls)
{
Control result = Find(child, id);
if (result != null)
{
return result;
}
}
**EDIT: **
I can access the controls in the edititemtemplate in the listview's ItemCreated event, however none they have no content (I'd assume the data hasn't been bound yet), so I can't get the key-value I need to do a lookup to get the data I need to populate the control.
I've figured out a way to do what I need to do, though I'm not terribly happy with it.
protected void UnitsLV_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (UnitsLV.EditIndex > -1)
{
// Controls within the edititemtemplate are available via e.Item.FindControl("controlname")
}
}
I don't know about previous editions but in Visual Studio 2010 you can easily access the edit item trhough the "ListView.EditItem" property like this:
private void myListView_ItemEditing(object sender, ListViewEditEventArgs e)
{
myListView.EditIndex = e.NewEditIndex;
myListView.DataBind();
ListViewItem lvwItem = lvwLista.EditItem;
ListBox tempLB = (ListBox) lvwItem.FindControl("ListBox3");
}
protected void ListView1_ItemUpdating(object sender, ListViewUpdateEventArgs e)
{
ListBox myListBox = (ListBox)(((ListView)sender).EditItem.FindControl("ListBox1"));
}
protected void UnitsLV_ItemEditing(object sender, ListViewEditEventArgs e)
{
ListViewItem item = UnitsLV.Items[e.NewEditIndex];
ListBox tempLB = (ListBox)e.item.FindControl("ListBox3");
}
I believe I found a typo in the above function. The second line should be
ListBox tempLB = (ListBox)item.FindControl("ListBox3");
What I did was replace "e.item" with "item"
I usually use the ItemDataBound Event... check the other options in ListItemType Enum
protected void UnitLV_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.EditItem)
{
ListBox myListBox = (ListBox) e.Item.FindControl("ListBox3");
}
}
this is similar to the accepted answer, but I think its author was really driving towards this:
protected void UnitsLV_ItemDataBound(object sender, ListViewItemEventArgs e)
{
ListViewDataItem listViewDataItem = e.Item as ListViewDataItem;
if (UnitsLV.EditIndex == listViewDataItem.DataItemIndex)
{
// Controls within the edititemtemplate are available via e.Item.FindControl("controlname")
}
}

Resources