开发者

ASP.NET Dynamic Data Filtering

I'd like to use ASP.NET Dynamic Data 4.0 with an EF POCO ObjectContext as a simple entity administration console for system administrators (I'm contemplating abandoning this technology...).

I've g开发者_如何转开发ot insert/update working.

I've figured out how to add filters for extra data types (because the built in ones are useless). I can't figure out how to make the QueryableFilterRepeater expose my columns as filtering. I can't added FilterUIHints to all applicable types, so that's not an acceptable solution. I do want to leverage the built in Entity Framework Metadata Model Provider. I don't want to write my own. The problem seems to boil down to the fact that the QueryableFilterIterator is calling MetaTable.GetFilteredColumns() and it's only returning bool/int/DateTime columns (which is useless).

I checked out ASP.NET Dynamic Data Filtering (http://dynamicdatafiltering.codeplex.com/), but it doesn't seem to be maintained for 4.0.

I guess I have two questions:

  1. Is there a way to do this (get my columns as filterable)?
  2. Is Dynamic Data actually suitable to use in the real world?


Got frustrated and took the direct route. If there's not a better solution to this...well, then Microsoft did a really poor job at this:

public class QueryableFilterRepeater : System.Web.DynamicData.QueryableFilterRepeater
    {
        private static readonly FieldInfo FiltersField = typeof(System.Web.DynamicData.QueryableFilterRepeater).GetField("_filters", BindingFlags.Instance | BindingFlags.NonPublic);
        private static readonly FieldInfo DataSourceField = typeof(System.Web.DynamicData.QueryableFilterRepeater).GetField("_dataSource", BindingFlags.Instance | BindingFlags.NonPublic);
        private static readonly MethodInfo FilterInitializeMethod = typeof(DynamicFilter).GetMethod("Initialize", BindingFlags.Instance | BindingFlags.NonPublic);
        private static readonly PropertyInfo FilterContextProperty = typeof(DynamicFilter).GetProperty("Context", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
        private static readonly MethodInfo PageInitCompleteMethod = typeof(System.Web.DynamicData.QueryableFilterRepeater).GetMethod("Page_InitComplete", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
        private static readonly EventInfo InitCompleteEvent = typeof(Page).GetEvent("InitComplete");

        private readonly List<DynamicFilter> filters;
        private int filterCount;
        private bool initialized;

        public IEnumerable<DynamicFilter> Filters
        {
            get { return filters; }
        }

        public QueryableFilterRepeater()
        {
            filters = (List<DynamicFilter>)FiltersField.GetValue(this);
        }

        private IQueryableDataSource DataSource
        {
            get { return DataSourceField.GetValue(this) as IQueryableDataSource; }
        }
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            InitCompleteEvent.RemoveEventHandler(Page, Delegate.CreateDelegate(typeof(EventHandler), this, PageInitCompleteMethod));

            Page.InitComplete += new EventHandler(Page_InitComplete);
        }

        protected override void OnLoad(EventArgs e)
        {
            filters.Select((f, i) => new { f, i }).Where(x => x.i > filterCount - 1).ToList().ForEach(x => filters.Remove(x.f));
            Controls.OfType<Control>().Select((c, i) => new { c, i }).Where(x => x.i > filterCount - 1).ToList().ForEach(x => Controls.Remove(x.c));
            base.OnLoad(e);
        }

        private void Page_InitComplete(object sender, EventArgs e)
        {
            if (!initialized)
            {
                Controls.Clear();
                filters.Clear();

                MetaTable metaTable = DataSource.GetMetaTable();
                int num = 0;
                foreach (MetaColumn column in metaTable.Columns)
                {
                    string filterUIHint = GetFilterUIHint(column);
                    if (filterUIHint == null) continue;

                    var filterRepeaterItem = new FilterRepeaterItem();
                    filterRepeaterItem.DataItemIndex = num;
                    filterRepeaterItem.DisplayIndex = num;
                    FilterRepeaterItem container = filterRepeaterItem;
                    num++;
                    ItemTemplate.InstantiateIn(container);
                    Controls.Add(container);
                    var dynamicFilter = container.FindControl(DynamicFilterContainerId) as DynamicFilter;
                    if (dynamicFilter == null)
                    {
                        throw new InvalidOperationException();
                    }
                    FilterContextProperty.SetValue(dynamicFilter, new HttpContextWrapper(Context), null);
                    dynamicFilter.DataField = column.Name;
                    container.DataItem = column;
                    container.DataBind();
                    container.DataItem = null;

                    dynamicFilter.FilterUIHint = filterUIHint;
                    filters.Add(dynamicFilter);
                    filterCount++;
                }
                filters.ForEach(f => FilterInitializeMethod.Invoke(f, new[] { DataSource }));
                initialized = true;
            }
        }

        private string GetFilterUIHint(MetaColumn column)
        {
            if (GetUnderlyingType(column.ColumnType) == typeof(string))
            {
                return "String";
            }
            if (GetUnderlyingType(column.ColumnType) == typeof(bool))
            {
                return "Boolean";
            }
            if (GetUnderlyingType(column.ColumnType).IsEnum)
            {
                return "Enumeration";
            }
            if (GetUnderlyingType(column.ColumnType) == typeof(DateTime))
            {
                return "DateTime";
            }
            if (column is MetaForeignKeyColumn)
            {
                return "ForeignKey";
            }
            if (column is MetaChildrenColumn)
            {
                return "Children";
            }

            return null;
        }

        private Type GetUnderlyingType(Type type)
        {
            return Nullable.GetUnderlyingType(type) ?? type;
        }

        // Nested Types

        #region Nested type: FilterRepeaterItem

        private class FilterRepeaterItem : Control, IDataItemContainer
        {
            // Properties

            #region IDataItemContainer Members

            public object DataItem { get; internal set; }
            public int DataItemIndex { get; internal set; }
            public int DisplayIndex { get; internal set; }

            #endregion
        }

        #endregion
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜