You cannot access the link tag <a> from the server in ASP.NET unless it has the runat="server" attribute. Here are your options:
1. Use the <ASP:Hyperlink> tag instead of the <a> tag.
If you don't mind letting ASP render the tags for you, just use their native hyperlink control.
PROS: You can access and manipulate the element from server and client side using a combination of CssClass and javascript, CSS, etc.
CONS: The tags would indeed be rendered by the server, so if you have a front-end engineer working with you, he might be at a disadvantage if he wanted to modify the layout.
2. Use Veena's solution and store the attribute value in a HiddenField
Create a <ASP:HiddenField> inside each of the list items that have a value equal to the tabindex of the corresponding <a> attribute.
PROS: You can use javascript to set the value of a HiddenField, so if you're building the field dynamically, it would work out. Also, no server-side element rendering is necessary like in option #1. This actually might be the most elegant solution if you are decent with javascript.
CONS: The actual tab-index attribute accessed by the server would be decoupled from its corresponding <a> tag. This will at best be an additional caveat to remember when working on that page, and at worst will cause unexpected behavior, exceptions, build-errors (probably not), etc. later on.
3. Add a runat="server" attribute to the link elements.
This would allow the server to see and access the element (albeit you may have to use one or two DirectCast functions). I'll include some code at the end of this answer that shows a method without conversion functions.
PROS: Simple. Will likely accomplish what you're trying to do in this specific case.
CONS: Some caveats exist when wrapping server controls inside HtmlGenericControls, so you'll have to keep this in mind if you decide to do more with the front-end code. To avoid this, you'll probably have to change your <div> wrapper into a <asp:PlaceHolder> tag--which I believe gets rendered as a div anyway.
If you want to go with option #3, here is a demonstration of how you would do it:
HTML
<asp:PlaceHolder runat="server" ID="test_PH">
<ul id="test_UL">
<li><a id="link1_undetectable" href="#" tabindex="0">Tab 0 - This will not be detected.</a></li>
<li><a id="link2_undetectable" href="#" tabindex="1">Tab 1 - This will not be detected.</a></li>
<li><a id="link3_undetectable" href="#" tabindex="2">Tab 2 - This will not be detected.</a></li>
<li><a id="link4_undetectable" href="#" tabindex="3">Tab 3 - This will not be detected.</a></li>
<li><a id="link5_undetectable" href="#" tabindex="4">Tab 4 - This will not be detected.</a></li>
<li><a id="link6" href="#" runat="server" tabindex="5">Tab 5</a></li>
<li><a id="link7" href="#" runat="server" tabindex="6">Tab 6</a></li>
<li><a id="link8" href="#" runat="server" tabindex="7">Tab 7</a></li>
<li><a id="link9" href="#" runat="server" tabindex="8">Tab 8</a></li>
<li><a id="link10" href="#" runat="server" tabindex="9">Tab 9</a></li>
</ul>
</asp:PlaceHolder>
VB.NET
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim ph As PlaceHolder = test_PH, sb As New StringBuilder() ' The string builder is just for demonstration purposes.
For Each c As HtmlAnchor In ph.Controls.OfType(Of HtmlAnchor)() ' This will loop through the HtmlAnchors without throwing an exception.
sb.AppendLine(String.Format("ID: ""{0}""; Tab-index: ""{1}""", c.ID, c.Attributes("tabindex"))) ' This builds a string for demo purposes.
Next
MsgBox(sb.ToString) 'Show the string for demo purposes.
End Sub
Result...
