1 using System.Collections.Generic; 2 using System.ComponentModel; 3 using System.Diagnostics; 4 using System.Diagnostics.CodeAnalysis; 5 using System.Globalization; 6 using System.Linq; 7 using System.Web.Resources; 8 using System.Web.UI; 9 using System.Web.UI.WebControls.Expressions; 10 using System.Web.UI.WebControls; 11 12 namespace System.Web.DynamicData { 13 /// <summary> 14 /// A templated control that automatically generates a collection of filters for a table associated with a given data source. 15 /// It is designed to work with the QueryExtender architecture and it will not render anything unless it's referenced by a 16 /// DynamicFilterExpression inside of a QueryExtender. 17 /// </summary> 18 [ParseChildren(true)] 19 [PersistChildren(false)] 20 public class QueryableFilterRepeater : Control, IFilterExpressionProvider { 21 private HttpContextBase _context; 22 private IQueryableDataSource _dataSource; 23 private List<DynamicFilter> _filters = new List<DynamicFilter>(); 24 private bool _initialized = false; 25 26 // for unit testing 27 private new HttpContextBase Context { 28 get { 29 return _context ?? new HttpContextWrapper(HttpContext.Current); 30 } 31 } 32 33 /// <summary> 34 /// The ID of a DynamicFilter control inside of the template that will be used configured to be a filter for a particular column. 35 /// The default value is "DynamicFilter" 36 /// </summary> 37 [ 38 Category("Behavior"), 39 DefaultValue("DynamicFilter"), 40 Themeable(false), 41 IDReferenceProperty(typeof(QueryableFilterUserControl)), 42 ResourceDescription("DynamicFilterRepeater_DynamicFilterContainerId") 43 ] 44 public string DynamicFilterContainerId { 45 get { 46 string id = ViewState["__FilterContainerId"] as string; 47 return String.IsNullOrEmpty(id) ? "DynamicFilter" : id; 48 } 49 set { 50 ViewState["__FilterContainerId"] = value; 51 } 52 } 53 54 /// <summary> 55 /// The template in which the layout of each filter can be specified. Just like ItemTempalte in Repeater. 56 /// </summary> 57 [Browsable(false)] 58 [DefaultValue(null)] 59 [PersistenceMode(PersistenceMode.InnerProperty)] 60 [TemplateContainer(typeof(INamingContainer))] 61 public virtual ITemplate ItemTemplate { get; set; } 62 QueryableFilterRepeater()63 public QueryableFilterRepeater() { 64 } 65 66 // for unit testing QueryableFilterRepeater(HttpContextBase context)67 internal QueryableFilterRepeater(HttpContextBase context) 68 : this() { 69 _context = context; 70 } 71 72 [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#")] OnPreRender(EventArgs e)73 protected override void OnPreRender(EventArgs e) { 74 if (_filters.Count == 0) { 75 this.Visible = false; 76 } 77 base.OnPreRender(e); 78 } 79 80 #region IFilterExpressionProvider Members 81 IFilterExpressionProvider.Initialize(IQueryableDataSource dataSource)82 void IFilterExpressionProvider.Initialize(IQueryableDataSource dataSource) { 83 if (dataSource == null) { 84 throw new ArgumentNullException("dataSource"); 85 } 86 87 if (ItemTemplate == null) { 88 return; 89 } 90 91 _dataSource = dataSource; 92 Page.InitComplete += new EventHandler(Page_InitComplete); 93 } 94 Page_InitComplete(object sender, EventArgs e)95 internal void Page_InitComplete(object sender, EventArgs e) { 96 if (_initialized) { 97 return; 98 } 99 100 Debug.Assert(_dataSource != null); 101 102 MetaTable table = DynamicDataExtensions.GetMetaTable(_dataSource, Context); 103 int itemIndex = 0; 104 foreach (MetaColumn column in table.GetFilteredColumns()) { 105 FilterRepeaterItem item = new FilterRepeaterItem() { DataItemIndex = itemIndex, DisplayIndex = itemIndex }; 106 itemIndex++; 107 ItemTemplate.InstantiateIn(item); 108 Controls.Add(item); 109 110 DynamicFilter filter = item.FindControl(DynamicFilterContainerId) as DynamicFilter; 111 if (filter == null) { 112 throw new InvalidOperationException( 113 String.Format(CultureInfo.CurrentCulture, 114 DynamicDataResources.FilterRepeater_CouldNotFindControlInTemplate, 115 ID, 116 typeof(QueryableFilterUserControl).FullName, 117 DynamicFilterContainerId)); 118 } 119 filter.Context = Context; // needed for unit testing 120 filter.DataField = column.Name; 121 122 item.DataItem = column; 123 item.DataBind(); 124 item.DataItem = null; 125 126 // Keep track of all the filters we create 127 _filters.Add(filter); 128 } 129 130 _filters.ForEach(f => f.Initialize(_dataSource)); 131 _initialized = true; 132 } 133 IFilterExpressionProvider.GetQueryable(IQueryable source)134 IQueryable IFilterExpressionProvider.GetQueryable(IQueryable source) { 135 foreach (DynamicFilter filter in _filters) { 136 source = ((IFilterExpressionProvider)filter).GetQueryable(source); 137 } 138 return source; 139 } 140 141 #endregion 142 143 private class FilterRepeaterItem : Control, IDataItemContainer { 144 public object DataItem { get; internal set; } 145 146 public int DataItemIndex { get; internal set; } 147 148 public int DisplayIndex { get; internal set; } 149 } 150 } 151 } 152