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?
- You can handle the DataBinding event of the FormView and set the visibility of controls in the depending upon a field's value.
- 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 NamespaceBy 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!