ASP.NET динамическая фильтрация данных - PullRequest
1 голос
/ 29 июля 2011

Я бы хотел использовать ASP.NET Dynamic Data 4.0 с EF POCO ObjectContext в качестве простой консоли администрирования сущностей для системных администраторов (я собираюсь отказаться от этой технологии ...).

У меня работает вставка / обновление.

Я выяснил, как добавить фильтры для дополнительных типов данных (потому что встроенные фильтры бесполезны). Я не могу понять, как заставить QueryableFilterRepeater выставлять мои столбцы в качестве фильтрации. Я не могу добавить FilterUIHints ко всем применимым типам, так что это неприемлемое решение. Я хочу использовать встроенный провайдер модели метаданных Entity Framework. Я не хочу писать свои собственные. Кажется, проблема сводится к тому, что QueryableFilterIterator вызывает MetaTable.GetFilteredColumns () и возвращает только столбцы bool / int / DateTime (что бесполезно).

Я проверил динамическую фильтрацию данных ASP.NET (http://dynamicdatafiltering.codeplex.com/),, но, похоже, она не поддерживается для 4.0.

Наверное, у меня есть два вопроса:

  1. Есть ли способ сделать это (сделать мои столбцы фильтруемыми)?
  2. Действительно ли динамические данные пригодны для использования в реальном мире?

1 Ответ

1 голос
/ 01 августа 2011

Разочаровался и выбрал прямой путь.Если нет лучшего решения для этого ... ну, тогда Microsoft проделала действительно плохую работу в этом:

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
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...