Visibility of Fields Within FormView

A quick trick that I'm sure many of you know.  Suppose you had a FormView on a page bound to a datasource.  Within that FormView, you have several fields that may or may not contain data.  Now, suppose that for whatever reason, your sponsor would like you to make a control and its label disappear if the corresponding field contained no data.  What are the different ways to achieve this simple requirement?

  1. You can handle the DataBinding event of the FormView and set the visibility of controls in the depending upon a field's value. 
  2. You can set the Visible property of the controls based upon a method defined in your page's code behind.  Possibly something like this:
    Public Function ShouldDisplay(ByVal text As Object) _
                                                    As Boolean
        If text Is DBNull.Value OrElse _
            String.IsNullOrEmpty(text.ToString.Trim) Then
            Return False
        Else
            Return True
        End If
    End Function

And then you can set the visible property of the controls like this:

<asp:Label ID="Label" 
           runat="server" 
           Visible='<%# ShouldDisplay(Eval("Description")) %>' 
           Text='<%# (Eval("Description")) %>'>
 </asp:Label>

3.  You can combine #1 and #2 and encapsulate this into something a little reusable.

Enter the ConditionalDisplayPanel.  This is something very simple which has potential to save you time over and over again.  To show how it works, here is the definition of a simple FormView control before applying the logic from above:

<asp:FormView ID="FormView2" 
              runat="server" 
              DataKeyNames="AttributeId" 
              DataSourceID="SqlDataSource1">
    <ItemTemplate>
        AttributeId:
        <asp:Label ID="AttributeIdLabel" 
                   runat="server" 
                   Text='<%# Eval("AttributeId") %>'>
       </asp:Label>
       <br />      
       AttributeName:
       <asp:Label ID="AttributeNameLabel" 
                  runat="server" 
                  Text='<%# Bind("AttributeName") %>'>
       </asp:Label>
       <br />
    </ItemTemplate>
</asp:FormView>

Now, in this example, suppose you don't want to display the AttributeName text or Label if there is no data in the AttributeName field in the datasource.  In that case, you simply wrap the AttributeName HTML with the ConditionalDisplayPanel like so:

<asp:FormView ID="FormView1" 
              runat="server" 
              DataKeyNames="AttributeId" 
              DataSourceID="SqlDataSource1">
    <ItemTemplate>
        AttributeId:
        <asp:Label ID="AttributeIdLabel" 
                   runat="server" 
                   Text='<%# Eval("AttributeId") %>'>
        </asp:Label><br /> 
        <sp:ConditionalDisplayPanel runat="server" 
                                    ID="pnlAttributeName" 
                                    FieldName="AttributeName">        
            AttributeName:
            <asp:Label ID="AttributeNameLabel" 
                       runat="server" 
                       Text='<%# Bind("AttributeName") %>'>
            </asp:Label>
            <br />
        </sp:ConditionalDisplayPanel>   
    </ItemTemplate>
</asp:FormView>

Please note the FieldName property on the ConditionalDisplayPanel.  This property tells the ConditionalDisplayPanel which field should be evaluated to determine if the contents of the control should be displayed.  At runtime during the binding of the controls in the FormView, the ConditionalDisplayPanel will evaluate the contents of that particular Field and if there is any data in the field, it will display the AttributeName HTML.  If not, then the opposite will happen.

Simple, no? 

Well, how does this work?  Actually, the ConditionalDisplayPanel was relatively simple to construct.  Here is the full class:

Namespace WebControls
    Public Class ConditionalDisplayPanel
        Inherits Panel

        Private _fieldName As String

        Public Property FieldName() As String
            Get
                Return _fieldName
            End Get
            Set(ByVal value As String)
                _fieldName = value
            End Set
        End Property

        Private Sub ConditionalPanel_DataBinding( _
ByVal sender As _
Object, _ ByVal e As _
System.EventArgs) _ Handles Me.DataBinding '// The naming container here (in a bindable context) '// implements the IDataItemContainer Dim container As IDataItemContainer = _ DirectCast(Me.NamingContainer, _
IDataItemContainer) '// Using the property of that container, '// DataItem, you can get at the DataRowView being bound. Dim row As Data.DataRowView = _ DirectCast(container.DataItem, _
Data.DataRowView) '// Retrieve the value from the row. Dim value As Object = row(Me.FieldName) '// Perform the comparison and set the Visible
'// Property Accordingly.
If value Is DBNull.Value OrElse _ String.IsNullOrEmpty(value.ToString.Trim) Then Me.Visible = False Else Me.Visible = True End If End Sub End Class End Namespace
By using this simple control, you can control this situation in one place for your entire application.  It could obviously be enhanced to perform many other checks, but as this was a 15 minute thing, I thought it would be best to keep it simple.

I hope this helps!

Enjoy!

Published 11 September 07 10:51 by Greg

Comments

# Samurai Programmer.com said on September 27, 2007 10:10 PM:

One of my friends suggested that I should provide a download for all of the little code snippets, controls,

Anonymous comments are disabled