This article originates from a post I ding on the ASP.NET Dynamic Data Forum here Re: A few problems with my dynamic data website, Rick Anderson suggesting that it would be a useful post to link to in his FAQ. So here it is for easy access rather than having to search the forum for it.
Firstly the idea is that you want to show the name of the entity but not link to if from the ForeignKey FieldTemplate.
Figure 1 - Category has Navigation disabled
The code we need for this comes in three parts
- The Attribute
- The modification the the FieldTemplate
- The Metadata.
The Attribute
C#
[AttributeUsage(AttributeTargets.Property)]
public class DisallowNavigationAttribute : Attribute
{
public Boolean Hide { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="DisallowNavigationAttribute"/> class.
/// </summary>
public DisallowNavigationAttribute()
{
Hide = false;
}
public DisallowNavigationAttribute(Boolean show)
{
Hide = show;
}
}
VB
<AttributeUsage(AttributeTargets.[Property] Or AttributeTargets.[Field])> _
Public Class DisallowNavigationAttribute
Inherits Attribute
Private _hide As [Boolean]
Public Property Hide() As [Boolean]
Get
Return _hide
End Get
Private Set(ByVal value As [Boolean])
_hide = value
End Set
End Property
Public Sub New(ByVal hide As [Boolean])
Me.Hide = hide
End Sub
Public Sub New()
Me.Hide = False
End Sub
End Class
Listing 1 – AllowNavigation attribute
Note the use of the Default see Writing Attributes and Extension Methods for Dynamic Data for the details on why.
C#
/// <summary>
/// Get the attribute or a default instance of the attribute
/// if the Column attribute do not contain the attribute
/// </summary>
/// <typeparam name="T">Attribute type</typeparam>
/// <param name="table">Column to search for the attribute on.</param>
/// <returns>The found attribute or a default instance of the attribute of type T</returns>
public static T GetAttributeOrDefault<T>(this MetaColumn column) where T : Attribute, new()
{
return column.Attributes.OfType<T>().DefaultIfEmpty(new T()).FirstOrDefault();
}
VB
Imports System.Runtime.CompilerServices
Imports System.Web.DynamicData
Public Module ExtensionMethods
''' <summary>
''' Get the attribute or a default instance of the attribute
''' if the Column attribute do not contain the attribute
''' </summary>
''' <typeparam name="T">Attribute type</typeparam>
''' <param name="column">Column to search for the attribute on.</param>
''' <returns>The found attribute or a default instance of the attribute of type T</returns>
''' <remarks>Used to simplify getting Attributes from metadata</remarks>
<Extension()> _
Public Function GetAttributeOrDefault(Of T As {Attribute, New})(ByVal column As MetaColumn) As T
Return column.Attributes.OfType(Of T)().DefaultIfEmpty(New T()).FirstOrDefault()
End Function
End Module
Listing 2 - Extension method to get attribute
The modification the the FieldTemplate
Now we need to add a little change to the ForeignKey.aspx.cs file which can be found in the ~/DynamicData/FieldTemplates folder of your Dynamic Data site.
C#
protected string GetNavigateUrl()
{
var dissallow = Column.GetAttributeOrDefault<DisallowNavigationAttribute>();
if (!AllowNavigation || dissallow.Hide)
{
// remove undeline :D
HyperLink1.Style.Add(HtmlTextWriterStyle.TextDecoration, "none !important");
return null;
}
if (String.IsNullOrEmpty(NavigateUrl))
{
return ForeignKeyPath;
}
else
{
return BuildForeignKeyPath(NavigateUrl);
}
}
VB
Protected Function GetNavigateUrl() As String
Dim dissallow = Column.GetAttributeOrDefault(Of DisallowNavigationAttribute)()
If Not AllowNavigation OrElse dissallow.Hide Then
Return Nothing
End If
If String.IsNullOrEmpty(NavigateUrl) Then
Return ForeignKeyPath
Else
Return BuildForeignKeyPath(NavigateUrl)
End If
End Function
Listing 3 – ForeignKey FieldTemplate modifications
Updated: With the addition of the inline style the underline will not show, of course you could always just set the CssClass of the Hyperlink to a style with textdecoration: none !important; if you wanted.
All we’ve done here is get the attribute into the allow variable and the add it to the checks in the if statement so that:
- If the internal AllowNavigation is set then null is returned.
- If the custom attribute is set null is returned.
The Metadata
C#
[MetadataTypeAttribute(typeof(Products.ProductsMetadata))]
public partial class Products
{
internal sealed class ProductsMetadata
{
public object ProductID { get; set; }
public object ProductName { get; set; }
public object QuantityPerUnit { get; set; }
public object UnitPrice { get; set; }
public object UnitsInStock { get; set; }
public object UnitsOnOrder { get; set; }
public object ReorderLevel { get; set; }
public object Discontinued { get; set; }
public object Order_Details { get; set; }
[DisallowNavigation(true)]
public object Categories { get; set; }
[DisallowNavigation(true)]
public object Suppliers { get; set; }
}
}
VB
Imports Microsoft.VisualBasic
Imports System.Web.DynamicData
Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations
<MetadataType(GetType([Product].[ProductMD]))> _
Partial Public Class [Product]
Partial Public Class [ProductMD]
Public ProductID As Object
Public ProductName As Object
Public SupplierID As Object
Public CategoryID As Object
Public QuantityPerUnit As Object
Public UnitPrice As Object
Public UnitsInStock As Object
Public UnitsOnOrder As Object
Public ReorderLevel As Object
Public Discontinued As Object
Public Order_Details As Object
<DisallowNavigationAttribute(True)> _
Public Category As Object
Public Supplier As Object
End Class
End Class
Listing 4 – sample Metadata
Now if you attribute a foreign key column up with the AllowNavigationAttribute you can turn off the hyperlink.
Happy Coding and remember 