views:

73

answers:

2

I find myself needing to preform the same actions on both HtmlControls and WebControls. I am a firm believer in DRY and find the fact that there is only the Control class to use if I want to consolidate the functions on both types. The problem that I have with using Control is that there certain properties that both HtmlControl and WebControl expose that Control does not. In the current case, the Attributes property is the problem. Does anyone have any suggestions on how to avoid the duplication of code in this type of instance?

+1  A: 

Hey,

I know what you mean. Theoretically, you could do one of the following:

  • Use reflection to assign some of those common settings.
  • Create a wrapper class that can take either a webcontrol or html control reference, and assign the values. (if control is webcontrol) assign value else if (html is htmlcontrol) assign value, something like that.
  • Create another logical class to store the common settings, then another component to copy those settings and apply them to the class.

Ultimately, there isn't any common bridge (no common base class or interface). What kind of assignments are we talking about?

Brian
In the particular case that I am working on, I need to set the class attributes. This is an ongoing issue as we move more and more of our existing code base to using jQuery. We need to be able to set the class attribute for both HtmlControls and WebControls through code to allow the client code to find them correctly.
David Williams
+1 for create a wrapper.
Kyle B.
I would recommend using the CssClass property for setting the class of a control. I would assume that you want to set specific classes for controls, not like setting a common class for all controls? If, to target with JQuery, as an example you want to have all textboxes implement the same CSS class, I think you may be able to use a .skin file to specify the class name for the <asp:TextBox runat="server" CssClass="MyClass"> control, as skins are server-side. Not 100% sure that will work, but it might be a viable option...
Brian
The other consideration is: do you want everything in markup, or in code for this? Using a wrapper is more code-oriented, though you can use public methods of the page or static methods within the markup directly. So I guess as another option, you may be able to use static methods directly in markup. Sorry for throwing so many things at you :-)
Brian
As I am currently doing code changes for user controls, where I need to set specific sets of controls contained within the user control (which could be either HtmlControls or WebControls), it is needed to handle both. Setting them in the markup does not work as the user controls can exist multiple times on the page, so I need to add the classes specific to the current instance.
David Williams
If all of your code is in user controls, you could create a custom user control base class (a class that inherits from UserControl), and within this class add a method that takes a control object and class, and does: if (control is WebControl) assign value else if (control is HtmlControl) assign value. That would work too, as yet another option.
Brian
A: 

In the past I've duplicated code to set the attributes for HtmlControls and WebControls. However, here's another idea:

Private Sub SetAttribute(ByRef ctrl As Control, ByVal key As String, ByVal value As String)
    If TypeOf ctrl Is HtmlControl Then
        DirectCast(ctrl, HtmlControl).Attributes(key) = value 
    ElseIf TypeOf ctrl Is WebControl Then
        DirectCast(ctrl, WebControl).Attributes(key) = value 
    End If
End Sub

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    For Each ctrl In Me.Controls
        SetAttribute(ctrl, "class", "classname")
    Next
End Sub        
Steve Wortham
This appears to be the cleanest approach. Thanks.
David Williams