/src/MVCContrib/UI/Grid/GridColumn.cs

https://github.com/dalager/MvcContrib · C# · 219 lines · 154 code · 32 blank · 33 comment · 7 complexity · 642f640ba68a8cc7b92eb9cf94352318 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using System.Text.RegularExpressions;
  7. using System.Web;
  8. namespace MvcContrib.UI.Grid
  9. {
  10. /// <summary>
  11. /// Column for the grid
  12. /// </summary>
  13. public class GridColumn<T> : IGridColumn<T> where T : class
  14. {
  15. private readonly string _name;
  16. private string _displayName;
  17. private bool _doNotSplit;
  18. private readonly Func<T, object> _columnValueFunc;
  19. private readonly Type _dataType;
  20. private Func<T, bool> _cellCondition = x => true;
  21. private string _format;
  22. private bool _visible = true;
  23. private bool _htmlEncode = true;
  24. private bool _sortable = false;
  25. private ColumnSortOptions _sortOptions;
  26. private readonly IDictionary<string, object> _headerAttributes = new Dictionary<string, object>();
  27. private List<Func<GridRowViewData<T>, IDictionary<string, object>>> _attributes = new List<Func<GridRowViewData<T>, IDictionary<string, object>>>();
  28. /// <summary>
  29. /// Creates a new instance of the GridColumn class
  30. /// </summary>
  31. public GridColumn(Func<T, object> columnValueFunc, string name, Type type)
  32. {
  33. _name = name;
  34. _displayName = name;
  35. _dataType = type;
  36. _columnValueFunc = columnValueFunc;
  37. }
  38. public bool Visible
  39. {
  40. get { return _visible; }
  41. }
  42. /// <summary>
  43. /// Name of the column
  44. /// </summary>
  45. public string Name
  46. {
  47. get { return _name; }
  48. }
  49. /// <summary>
  50. /// Display name for the column
  51. /// </summary>
  52. public string DisplayName
  53. {
  54. get
  55. {
  56. if(_doNotSplit)
  57. {
  58. return _displayName;
  59. }
  60. return SplitPascalCase(_displayName);
  61. }
  62. }
  63. /// <summary>
  64. /// The type of the object being rendered for thsi column.
  65. /// Note: this will return null if the type cannot be inferred.
  66. /// </summary>
  67. public Type ColumnType
  68. {
  69. get { return _dataType; }
  70. }
  71. public bool IsSortable { get { return _sortable; } }
  72. IGridColumn<T> IGridColumn<T>.Attributes(Func<GridRowViewData<T>, IDictionary<string, object>> attributes)
  73. {
  74. _attributes.Add(attributes);
  75. return this;
  76. }
  77. /// <summary>
  78. /// Custom header renderer
  79. /// </summary>
  80. public Action<RenderingContext> CustomHeaderRenderer { get; set; }
  81. /// <summary>
  82. /// Custom item renderer
  83. /// </summary>
  84. public Action<RenderingContext, T> CustomItemRenderer { get; set; }
  85. /// <summary>
  86. /// Additional attributes for the column header
  87. /// </summary>
  88. public IDictionary<string, object> HeaderAttributes
  89. {
  90. get { return _headerAttributes; }
  91. }
  92. /// <summary>
  93. /// Additional attributes for the cell
  94. /// </summary>
  95. public Func<GridRowViewData<T>, IDictionary<string, object>> Attributes
  96. {
  97. get { return GetAttributesFromRow; }
  98. }
  99. private IDictionary<string, object> GetAttributesFromRow(GridRowViewData<T> row)
  100. {
  101. var dictionary = new Dictionary<string, object>();
  102. var pairs = _attributes.SelectMany(attributeFunc => attributeFunc(row));
  103. foreach(var pair in pairs)
  104. {
  105. dictionary[pair.Key] = pair.Value;
  106. }
  107. return dictionary;
  108. }
  109. public IGridColumn<T> Named(string name)
  110. {
  111. _displayName = name;
  112. _doNotSplit = true;
  113. return this;
  114. }
  115. public IGridColumn<T> DoNotSplit()
  116. {
  117. _doNotSplit = true;
  118. return this;
  119. }
  120. public IGridColumn<T> Format(string format)
  121. {
  122. _format = format;
  123. return this;
  124. }
  125. public IGridColumn<T> CellCondition(Func<T, bool> func)
  126. {
  127. _cellCondition = func;
  128. return this;
  129. }
  130. IGridColumn<T> IGridColumn<T>.Visible(bool isVisible)
  131. {
  132. _visible = isVisible;
  133. return this;
  134. }
  135. public IGridColumn<T> DoNotEncode()
  136. {
  137. _htmlEncode = false;
  138. return this;
  139. }
  140. IGridColumn<T> IGridColumn<T>.Sortable(bool isDefault)
  141. {
  142. _sortable = true;
  143. _sortOptions = new ColumnSortOptions();
  144. _sortOptions.IsDefault = isDefault;
  145. return this;
  146. }
  147. public ColumnSortOptions SortOptions { get { return _sortOptions; } }
  148. IGridColumn<T> IGridColumn<T>.HeaderAttributes(IDictionary<string, object> attributes)
  149. {
  150. foreach(var attribute in attributes)
  151. {
  152. _headerAttributes.Add(attribute);
  153. }
  154. return this;
  155. }
  156. private string SplitPascalCase(string input)
  157. {
  158. if(string.IsNullOrEmpty(input))
  159. {
  160. return input;
  161. }
  162. return Regex.Replace(input, "([A-Z])", " $1", RegexOptions.Compiled).Trim();
  163. }
  164. /// <summary>
  165. /// Gets the value for a particular cell in this column
  166. /// </summary>
  167. /// <param name="instance">Instance from which the value should be obtained</param>
  168. /// <returns>Item to be rendered</returns>
  169. public object GetValue(T instance)
  170. {
  171. if(! _cellCondition(instance))
  172. {
  173. return null;
  174. }
  175. var value = _columnValueFunc(instance);
  176. if(!string.IsNullOrEmpty(_format))
  177. {
  178. value = string.Format(_format, value);
  179. }
  180. if(_htmlEncode && value != null)
  181. {
  182. value = HttpUtility.HtmlEncode(value.ToString());
  183. }
  184. return value;
  185. }
  186. }
  187. }