ASP.NET bind single instance data - asp.net

I have a data class that I want to show in a list on one page and also alone in another page. I know how to do the first:
<asp:Repeater ID="ctrl" runat="server">
<ItemTemplate>
Here's the name: <asp:Literal runat="server" Text='<%# Eval("Name") %>' />
</ItemTemplate>
</asp:Repeater>
On the other page, I want to show exactly one instance, and I want to reuse the item template. Is there a control that I can bind to a single instance of this class, instead of a list which contains a single element?

You can use the same Repeater but with a DataSource of on specific record/instance.
You can also use FormView control.
The FormView control gives you the ability to work with a single record from a data source. The FormView control does not specify a pre-defined layout for displaying the record. Instead, you create a template containing controls to display individual fields from the record. For information about programming the FormView control, see FormView Class in the MSDN library.

Related

Container id structure on controls added to placeholder in repeater

Just ran across a weird thing. We have a page with items rendered in a Repeater. The items in the list have one panel for display and a PlaceHolder for edit mode where controls are added in the item data binding.
We have some client side code working with the fields that got added, and the code was expecting the ids to follow the same container structure you usually see, but for some reason, one level is getting skipped and I don't know why.
With the template below, you'd have the outer panel with an id like ...Repeater_ctl46_ctl100_Display. The PlaceHolder itself doesn't render, nor get included in the id structure in the html, but the id of a HiddenField added to the EditPlaceHolder ends up like ...Repeater_ctl46_ctl100_valueHidden.
The _Display level just doesn't appear. This threw off our client side script because it was expecting the outer panel container to be reflected in all the child controls in the edit template, and it was using that to look them up.
Anyone know why the containing Panel wouldn't be in the id hierarchy?
<ItemTemplate>
...
<asp:Panel ID="Display" runat="server">
<asp:Panel ID="ViewPanel" runat="server"><asp:Label ID="ValueLabel" runat="server" /></asp:Panel>
<asp:PlaceHolder ID="EditPlaceHolder" runat="server" />
</asp:Panel>
<asp:Panel ID="ModButtons" runat="server"><asp:LinkButton ID="EditButton" Text="<%$ Resources:Messages,Edit %>" runat="server" /></asp:Panel>
...
</ItemTemplate>
Okay, after a lot of digging, asp:Panel does not implement INamingContainer, which is why the Panel is not participating in the id naming conventions.
INamingContainer is just a marker interface; it has no properties or methods associated.
So if you want a Panel that can participate in naming conventions, you can make a little derivation and use that instead:
public class NamingPanel : Panel, INamingContainer
{...}

vb asp.net : A way to avoid repeating a code in common in ItemTemplate and EditItemTemplate

I'm a newbie in asp.net.
When using FormView, there is a big amount of code in ItemTemplate, EditItemTemplate and InsertItemTemplate which is almost identical.
For example:
<asp:ListBox ID="ListBox2" runat="server" Rows="1" CssClass="field"
DataSourceID="StatusList" DataTextField="DESCRIPTION"
DataValueField="STAT_ID" SelectedValue='<%# Bind("STAT_ID") %>'>
</asp:ListBox>
(Note: at the exception that Eval() would be used instead of Bind() in ItemTemplate)
I've been trying to avoid repeating this code but without the expecting result:
ListView allows the use of LayoutTemplate - but I didn't see any examples that insert this kind of code in LayoutTemplate. And inserting this code in LayoutTemplate would result in an error.
DetailView allows to produce code automatically but I'd like to use a specific design (for ex. using "fieldset" that encompasses some fields).
What would be the best way to avoid repeating this kind of code ?
You don't have to much choice about seperately specifying the Bind/Eval part, but you do have some control over the other pieces. You can make a custom UserControl that contains your layout.
Usually I include a property on this usercontrol called "Mode" which I either set to Edit or View, then based off of this property I change enabled/visible properties on the controls. You'll also need to include a property for each value you want bound/displayed in the usercontrol.
Put some labels, textboxes, etc... in your designer and hook them up to properties in your code behind, put the usercontrol on your page in your item/edit template and eval/bind to your data to the various properties (make sure to set the mode so it displays right).

Nested Repeater not being recognised in code behind

I have a nested repeater set up but the child repeater control is not being recognised in the code behind. It's not even being added to the designer file. I've tried this on an aspx and an ascx page but both gives the same problem.
<asp:Repeater ID="RepeaterParent" runat="server">
<ItemTemplate>
<asp:Repeater ID="RepeaterChild" runat="server">
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
with this on the page the code behind only recognises the RepeaterParent but not RepeaterChild.
Can anyone help me out here?
Many thanks!
Like any other control that is used within a repeater (or template) control, you need to retrieve the control using FindControl.
So, in your item data bind event handler for the parent, you would do:
var childRepeater = RepeaterParent.FindControl("RepeaterChild") as Repeater;
The RepeaterChild will be accessible when you use FindControl("RepeaterChild") on the parent repeater I think. Can't remember the exact syntax.
Also note that the FindControl method will also take the context of the current item of the parent repeater, as the name you specify will repeat. Naming containers do some work in the background to provide unique naming, but it is hard to track sometimes.

Two-way data binding of controls in a user control nested inside a FormView doesn't work

I'm trying to perform two-way data binding on the controls in my user control, which is hosted inside a FormView template:
<asp:ObjectDataSource runat="server" ID="ObjectDataSource"
TypeName="WebApplication1.Data" SelectMethod="GetItem" UpdateMethod="UpdateItem">
</asp:ObjectDataSource>
<asp:FormView runat="server" ID="FormView" DataSourceID="ObjectDataSource">
<ItemTemplate>
<uc:WebUserControl1 runat="server"></uc:WebUserControl1>
</ItemTemplate>
<EditItemTemplate>
<uc:WebUserControl1 runat="server"></uc:WebUserControl1>
</EditItemTemplate>
</asp:FormView>
The web user control:
<%# Control Language="C#" ... %>
<asp:TextBox runat="server" ID="TitleTextBox" Text='<%# Bind("Title") %>'>
</asp:TextBox>
The binding works fine when the FormView is in View mode but when I switch to Edit mode, upon calling UpdateItem on the FormView, the bindings are lost. I know this because the FormView tries to call an update method on the ObjectDataSource that does not have an argument called 'Title'.
I tried to solve this by implementing IBindableTemplate to load the controls that are inside my user control, directly into the templates (as if I had entered them declaratively). However, when calling UpdateItem in edit mode, the container that gets passed into the ExtractValues method of the template, does not contain the TextBox anymore. It did in view mode!
I have found some questions on SO that relate to this problem but they are rather dated and they don't provide any answers that helped me solve this problem.
How do you think I could solve this problem? It seems to be such a simple requirement but apparently it's anything but that...
My current workaround for this is, although rather cumbersome, to subclass the FormView class and use subclassed controls in it, implementing my own data binding logic (taking the data field name from a new property) instead of using the <%# %> syntax. Apparently, the code the latter generates is the real culprit here as it doesn't support this nested control scenario.
I ended up, using old asp include statement
<--%include file = "filename" -->
instead of using user controls for dealing with the code duplication issue.

ASP.NET: How to assign ID to a field in DetailsView?

I have a master-detail page, in which I use GridView to display multiple rows of data, and DetailsView + jQuery dialog to display the details of a single records. only one DetailsView is open at a time.
I need to be able to pull out a single field of the open DetailsView, for manipulation using JavaScript. Is there a way to give a unique ID to a given field in DetailsView, so I can use getElementByID? Or is there another way to accomplish what I'm trying to do?
Thank you in advance.
If you are using a bound textbox in a template field in your detailsview you can then select it by:
$("[id$='MyTextBox']");
Which will find the textbox bound to MyFieldName as below.
<asp:DetailsView ID="DetailsView1" runat="server">
<Fields>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="MyTextBox" Text='<%# Bind("MyFieldName")%>' runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
Whatever guff asp.net adds onto the begining of the id won't matter because jQuery $= mean "ends with".
there may be a better way, but when I've needed an id available for js work, I just convert the bound field to a templated field. you can then give the textbox the id of your choice. keep in mind when rendered the id will be expanded with the id of the parent control.

Resources