2013年2月4日 星期一

取得 Entity 類別 MetaData 所設定的 Display Name

在「ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 Part.4:分頁進階處理」的文章當中,我把資料的欄位排序改以表格的標題欄位來操作,因為那一篇文章只是做個範例,所以就直接以 Entity 的 Property 名稱作為標題來顯示,而實際的應用狀況下,我們的 Entity Property 名稱並不會直接顯示在頁面上,而是會另外以 DisplayAttribute 來標註要顯示的名稱,然後頁面上就顯示這個 Display Name。

不過有個朋友就在該文章回應並且提供一個方法,讓表格的標題改用 Display Name 來顯示,看了這位朋友所提供的方法後,覺得這個方法是可以達到需求,但還可以在做些修改,讓修改後的方法不只有提供給 View 做顯示之用,在其他有需要的地方,只要呼叫這個修改後的方法就可以輕易取得 Entity 類別中某個 Property 上的 Display Name。

 


我這次以 VS2012, ASP.NET MVC 4 做開發,而程式的部份並沒有做任何的變動,除了前端的畫面做些調整之外,其餘的都跟之前「ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 Part.4:分頁進階處理」內的都一樣,

image

image

image

image

 

修改

我這邊仍然是使用 ADO.NET Entity Framework Database First 來建立 ASP.NET MVC 網站的 Model,然後另外為 Entity 建立 Partial Class 以建立 MetaData Class,

image

在 Customers 的 Partial Class 中建立了 CustomersMetaData 類別,然後為各個 Property 加上 DisplayAttribute 以及給予 Name 值,接下來我們要做的就是把這個 Display Name 給顯示到表格得標提列上,

image

因為我們要可以在表格標題列點選標題後去依照標題所屬欄位的資料排序變化,所以無法以一般的 HtmlHelper.DisplayName 來處理,所以之前就用以下的方法,

#region -- SortColumnLink --
/// <summary>
/// sort column HyperLink.
/// </summary>
/// <param name="columnName">Name of the column.</param>
/// <returns></returns>
private MvcHtmlString SortColumnLink(string columnName)
{
    string result = string.Format("<a class=\"sortColumnLink\" href=\"{0}\" id=\"{0}_{1}\">{2}</a>",
        columnName,
        "asc",
        columnName);
 
    if (columnName.Equals(this.SortColumnName, StringComparison.OrdinalIgnoreCase))
    {
        string sortColumnLink = string.Format("<a class=\"sortColumnLink\" href=\"{0}\" id=\"{0}_{1}\" style=\"color: red;\">{2} {3}</a>",
            columnName,
            this.SortType,
            columnName,
            this.SortType.Equals("asc", StringComparison.OrdinalIgnoreCase) ? "▲" : "▼");
 
        result = sortColumnLink;
    }
 
    return MvcHtmlString.Create(result);
}
 
#endregion

然後在前端的 View 頁面就用這樣方式將欄位名稱代入,就有可以處理排序的標題連結產生,

image

不過之前的寫法只會顯示 Entity 的欄位名稱,所以為了要可以顯示 MetaData 所標註的 DisplayAttribute Name,我先增加了以下的類別,用來取得 Entity 的欄位於 MetaData 所標註的 Display Name,

DisplayAttributeHelper

public class DisplayAttributeHelper<TModel> where TModel : class
{
    #region -- GetDisplayName --
 
    /// <summary>
    /// Gets the display name.
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    /// <returns></returns>
    public static string GetDisplayName(string propertyName)
    {
        Type type = typeof(TModel);
        Type metaDataType = null;
 
        foreach (MetadataTypeAttribute attrib in type.GetCustomAttributes(typeof(MetadataTypeAttribute), true))
        {
            metaDataType = attrib.MetadataClassType;
        }
 
        if (metaDataType == null)
        {
            return propertyName;
        }
 
        PropertyInfo pInfo = GetProperty(type, propertyName);
        return DisplayAttributeHelper<TModel>.GetDisplayName(pInfo, metaDataType);
    }
 
    /// <summary>
    /// Gets the property.
    /// </summary>
    /// <param name="type">The type.</param>
    /// <param name="propName">Name of the prop.</param>
    /// <returns></returns>
    private static PropertyInfo GetProperty(Type type, string propName)
    {
        try
        {
            PropertyInfo[] infos = type.GetProperties();
            if (infos == null)
            {
                return null;
            }
            foreach (PropertyInfo info in infos)
            {
                if (propName.ToLower().Equals(info.Name.ToLower()))
                {
                    return info;
                }
            }
        }
        catch (Exception ex)
        {
            return null;
            throw ex;
        }
        return null;
    }
 
    /// <summary>
    /// Gets the property Display Name.
    /// </summary>
    /// <param name="pInfo">The p info.</param>
    /// <returns></returns>
    public static string GetDisplayName(PropertyInfo pInfo, Type metaDataType)
    {
        if (null == pInfo)
        {
            return String.Empty;
        }
 
        string propertyName = pInfo.Name;
 
        DisplayAttribute attr = (DisplayAttribute)metaDataType.GetProperty(propertyName)
            .GetCustomAttributes(typeof(DisplayAttribute), true)
            .SingleOrDefault();
 
        if (attr == null)
        {
            MetadataTypeAttribute otherType =
                (MetadataTypeAttribute)metaDataType.GetCustomAttributes(typeof(MetadataTypeAttribute), true)
                .FirstOrDefault();
 
            if (otherType != null)
            {
                var property = otherType.MetadataClassType.GetProperty(propertyName);
                if (property != null)
                {
                    attr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayNameAttribute), true).SingleOrDefault();
                }
            }
        }
        return (attr != null) ? attr.Name : String.Empty;
    }
 
    #endregion
 
}

建立 DisplayAttributeHelper 類別後,以後取得 Display Name 就輕鬆多了,而且也不必在程式中把類別寫死。

 

接著我們就修改 CustomersController 原本 SortColumnLink Method 的程式內容,修改如下:

#region -- SortColumnLink --
/// <summary>
/// sort column HyperLink.
/// </summary>
/// <param name="columnName">Name of the column.</param>
/// <returns></returns>
private MvcHtmlString SortColumnLink(string columnName)
{
    string displayName = DisplayAttributeHelper<Customers>.GetDisplayName(columnName);
 
    string result = string.Format("<a class=\"sortColumnLink\" href=\"{0}\" id=\"{0}_{1}\">{2}</a>",
        columnName,
        "asc",
        displayName);
 
    if (columnName.Equals(this.SortColumnName, StringComparison.OrdinalIgnoreCase))
    {
        string sortColumnLink = string.Format("<a class=\"sortColumnLink\" href=\"{0}\" id=\"{0}_{1}\" style=\"color: red;\">{2} {3}</a>",
            columnName,
            this.SortType,
            displayName,
            this.SortType.Equals("asc", StringComparison.OrdinalIgnoreCase) ? "▲" : "▼");
 
        result = sortColumnLink;
    }
 
    return MvcHtmlString.Create(result);
}
 
#endregion

執行結果:

image

image

image

 


延伸閱讀:

Dynamic LINQ + Entity Framework - Part.4:ASP.NET MVC 進階應用

ASP.NET MVC 3 - ViewBag 裡使用方法(Method)

 

以上

6 則留言:

  1. 想問個跟文章沒有關係的問題
    請問您的 Visual Studio color schemes 哪邊可以抓到?
    覺得看起來很舒服 ~ 謝謝!

    回覆刪除
    回覆
    1. 我用的是 monokai-bright-sublime,不過我還是做了一些設定的更改。

      刪除
  2. 感謝提供更完整的方式
    來處理

    回覆刪除
    回覆
    1. 其實這個方法是我原本應用在其他功能時就有做的,只是沒有想到要用在之前的範例中,
      經你上次的分享後,我才修改原有的方法來應用在之前的範例中。

      刪除
  3. 剛剛自己找了一下 color schemes 應該是 Sublime 2

    回覆刪除
    回覆
    1. StudioStyles : Monokai Bright - Sublime
      http://studiostyl.es/schemes/monokai-bright-sublime

      刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。

最近的留言