12

ASP.Net 4.5 introduces new ways to bind data to controls like the Repeater through the SelectMethod property:

<asp:Repeater runat="server" ItemType="MyData.Reference" 
      SelectMethod="GetReferences">

calls the Codebehind method

public IEnumerable<Reference> GetReferences()

In the scenario of nested repeaters, is it possible to pass a parameter to this select method somehow, so that it fetches different data depending on the Item of the outer repeater?

Example:

<asp:Repeater runat="server" ItemType="MyData.Reference" 
        SelectMethod="GetReferences(Item.ID)">

should be calling

public IEnumerable<Reference> GetReferences(int id)

I know this can be achieved through ItemDataBound events, but I would like to use the much simpler and cleaner syntax of SelectMethod and ItemType.

Does the SelectMethod allow parameter passing somehow?

If not, is there another clean way to get the value from the outer Repeater Item within my SelectMethod?

Mikhail
  • 9,186
  • 4
  • 33
  • 49
magnattic
  • 12,638
  • 13
  • 62
  • 115

5 Answers5

9

While waiting for answers, I played around a bit and found the following solution.

It might not be the best way to do it, but so far I have found no problems with it and it's pretty straigtforward, so I'll just throw it out there.

<asp:Repeater runat="server" ItemType="MyData.Reference" 
     DataSource='<%# GetReferences(Item.ID) %>'>

Essentially what I do here is replace the SelectMethod with DataSource (Intellisense will not suggest it, but it works nonetheless).

This way I can pass a value to the GetReferences method and then uses the return value for model binding.

So far this is the shortest solution I came across.

magnattic
  • 12,638
  • 13
  • 62
  • 115
6

Here is how you do it:

In your outer repeater, place a hidden field, and name a selectmethod for inner repeater:

<asp:Repeater SelectMethod="GetTopLevelStuff">
   <ItemTemplate>       
       <asp:HiddenField runat="server" ID="ItemId" Value="<%# Item.ID %>"/>
       <asp:Repeater SelectMethod="GetSubItems">
           <ItemTemplate>Template code for sub-items here</ItemTemplate
       </asp:Repeater>
   </ItemTemplate
</asp:Repeater>

Then, here's the not-so-well-documented-magic:

 public IQueryable<SubItem> GetSubItems([Control("ItemId")] int itemId)
    {
        return yourDataStore.GetSubItems(itemId);
    } 

The valueprovider in this case can also take a propertyname, useful when using listboxes to get "SelectedValue".

I found your question, did as you did, then I tried this solution instead which works just as well but is much cleaner and more according to the idea of the concept, it seems.

LavaEater
  • 129
  • 1
  • 2
  • Interesting. I don't like though that you generate markup that is basically useless for the client or subsequent postbacks. – magnattic Feb 15 '13 at 13:47
  • Do you mean the ItemID-control itself? If you want to avoid useless markup I would move away from WebForms and start looking at asp.net MVC or using Knockout.js - then you can actually wield control over your markup. I see what you mean, though. – LavaEater Feb 19 '13 at 07:38
2

Take a look at the Exercise 1: Model Binding in ASP.NET Web Forms -> Task 3 – Value Providers in Model Binding tutorial.

It is possible to define a some kind of the Control Select Parameter within the SelectMethod signature.

Mikhail
  • 9,186
  • 4
  • 33
  • 49
  • That sounds good in general, but I'm not sure I can use it for my work case. How would I use value providers to pass the Item ID from my outer repeater? – magnattic Oct 09 '12 at 19:03
1

You can use Value Providers

Example:

public IQueryable<Category> GetCategories([Control]int? minProductsCount)
{
}

This a list of ValueProviders:

Jupaol
  • 21,107
  • 8
  • 68
  • 100
0

I think the SelectArguments property exists for exactly this purpose: https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.repeater.selectarguments?view=netframework-4.8.1

Protector one
  • 6,926
  • 5
  • 62
  • 86