In my last post, I showed how you can use Dynamic Data with the FormView and similar controls to autogenerate UI controls and associated validation based on data annotations. The one downside was that the scaffolded HTML is horrible – and fixing it is nowhere near as easy as you might hope.
This is some of the markup generated by the wizard in Visual Studio:
This is what the output looks like – notice the horrible ragged edge and the use of inaccessible LinkButtons:
And this is a snippet from generated HTML:
So – we have text where we should have a label, making our page both inaccessible and less functional than it should be, and we have a link button where should have a submit button. We can fix the button just by changing the type, and we can fix the ragged edge by adding in extra line breaks. But it turns out that the labels are much more of a problem than they might at first appear.
First, let’s try adding a label and pointing it at the dynamic control:
That looks like it ought to work… And at first sight, the generated Web page looks a lot better when we run it. The label is now on a separate line from the TextBox, and the styling shows that it is truly is a label control, and not just text:
Unfortunately, it’s not as good as it seems at first glance. A look at the HTML source shows that this label is not properly connected to its TextBox: the for and the id do not match.
The usual fix in these circumstances is to switch to static client side ids. So let’s try replacing our ASP.NET label with a simple HTML label, and setting the dynamic control to have a static ClientIDMode:
Here’s what we get when we run it:
Okay – so let’s try harder by setting the ClientIDMode of the FormView itself to Static and see if that will do the trick…
Unfortunately, that doesn’t help either – though, refreshingly, the problem is different:
Fundamentally, the problem is that the DynamicControl is a container. We need the label to be associated with the TextBox inside the DynamicControl.
First, let’s get rid of those Static ClientIDMode values, as we can’t have every TextBox with the id TextBox. Then let’s see if we can bind the value of the for attribute to the ClientID property of the control. We have to do a bit of digging to get there, as the TextBox is inside a FieldTemplate which is inside the DynamicControl, which is inside the FormView:
And this is the output HTML:
Finally, we have a winner. Except for the fact that Dynamic Data is supposed to simplify the generation of the UI, and there is nothing remotely simple about having to add labels with custom data binding code that includes nested FindControl() methods.
Fortunately, our quest for automated client side data annotation validation does not end there – because it’s possible to customize the templates for DynamicControls, and that offers a much more practical and satisfying solution to the problem of poor scaffolding. And that will be the subject of my next blog post.
For other related information, check out these courses from Learning Tree: