Опять про бизнес объекты

отредактировано 04:06 Раздел: FastReport .NET
Наткнулся на фичу.
Имеем бизнес обект Class1:
public class Class1
    {
        public Class1(string name)
        {
            this.name = name;
        }

        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private Class2 cl2;
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public Class2 CL2
        {
            get { return cl2; }
            set { cl2 = value; }
        }

    }

    public class Class2
    {
        public Class2(string name)
        {
            this.name = name; 
        }

        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private List<Class3> list;

        public List<Class3> CL3List
        {
            get { return list; }
            set { list = value; }
        }

    }

    public class Class3
    {
        public Class3(string name)
        {
            this.name = name;
        }
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }

инициализируем его:
            Class1 cl1 = new Class1("Class1");
            List<Class3> list = new List<Class3>();
            list.Add(new Class3("1 Class 3 "));
            list.Add(new Class3("2 Class 3 "));
            list.Add(new Class3("3 Class 3 "));

            Class2 cl2 = new Class2("Class 2");
            cl2.CL3List = list;

            cl1.CL2 = cl2;

в PropertyGrid он выглядит так:
0sIEnRL3SA.jpg

передаем в FastReport:
List<Class1> l = new List<Class1>();
l.Add(cl1);
Report report = new Report();
report.RegisterData(l, "Class1", FastReport.Data.BOConverterFlags.BrowsableOnly, 5);
report.Design();

в окне выбора данных вот что:
Y73YRifSR2.jpg

свойство CL3List отображается как свойство Class1, а не как свойство СL2!

а если свойство CL2 класса Class1 объявить как
private List<Class2> cl2;
         public List<Class2>CL2
        {
            get { return cl2; }
            set { cl2 = value; }
        }

и внести далее соответствующие изменения, то свойство CL3List отображается как надо, т.е. как свойство списка СL2.

так вот вопрос, возможно-ли исправить эту ситуацию, чтоб в обих случаях CL3List отображается как свойство СL2?
Подозреваю, что если Class2 объявить как public class Class2: IEnumerable и реализовать необходимую логику все заработает как надо....

Комментарии

  • отредактировано 04:06
    Это действительно "фича", с которой придется смириться. В списке "Выбрать данные", а так же в окне "Данные", отображается иерархия источников данных, а это не совсем то же самое, что иерархия классов. В данном случае Class2 - это всего лишь комплексное св-во класса Class1, но никак не источник данных. Источники данных - это классы Class1 и Class3, и именно они связаны отношением master-detail.
  • отредактировано 04:06
    Ясно, спасибо.
    Вот еще что, если Class2 обявлен как public class Class2<T> where T : new () (вообщем как generic), то в FastReport его тип (DataType) определится как Class2`1
  • отредактировано 04:06
    Это он так в окне "Свойства" показывает, а в файл пишет полное имя. Правда, если перетащить такое поле в скрипт, создастся неправильный код для доступа к нему. Это попробую исправить.
  • отредактировано 04:06
    Рецепт преобразовывания комплексного свойства в источник данных (может кому пригодится):
    У структуры из 1го поста Class2 - комплексное свойство, чтобы FastReport воспринемал его как источник данных внести изменения:
        public class Class2 : IEnumerable
        {
            //... все тоже самое что и в оригинале
    
            #region IEnumerable Members
    
            public IEnumerator GetEnumerator()
            {
                return new Class2Enumerator(this);
            }
    
            #endregion
        }
    

    и добавить класс Class2Enumerator:
        public class Class2Enumerator : IEnumerator
        {
            private int position = -1;
            private Class2 _cl2;
            public Class2Enumerator(Class2 cl2)
            {
                _cl2 = cl2;
            }
    
            #region IEnumerator Members
    
            public object Current
            {
                get
                {
                    if (position == 0)
                        return _cl2;
                    else
                        throw new InvalidOperationException();
                }
            }
    
            public bool MoveNext()
            {
                position++;
                return position < 1;
            }
    
            public void Reset()
            {
                position = -1;
            }
    
            #endregion
        }
    

    в результате получаем:
    VYKu1qOWtR.jpg

    kPWVnT0L11.jpg
  • отредактировано 04:06
    Обновил версию :-)
    Раньше ведь другое поведение было ? (в версии 1.064 точно)
    Вообщем ситуация следующая
    class CollectionBase <T>
    {
      [Description("Items")]
      public List<T> Items {get;}
    }
    
    
    class Collection1 : CollectionBase <Item> {/*some specific fields*/}
    class Collection2 : CollectionBase <Item> {/*some specific fields*/}
    
    class CompositeReportElement 
    {
      Collection1 Collection1 {get;}
      Collection2 Collection2 {get;}
    }
    
    

    в дата соурсе вижу только одну коллекцию Items
    1 в отчете надо получить две таблицы с хидерами для Collection1 и Collection2 как быть ?
    правильно ли будет так как предложил Domoch,
    class CollectionBase <T, CollectionT> : IEnumerable<CollectionT>
    {
    
      public IEnumerator<CollectionT> GetEnumerator<CollectionT>(){yield return this;}
      ...
    }
    
    обязательно ли в этом случае датабенд вешать на свойства Collection1 и Collection2, или он по умолчанию 1-ю запись возмет?

    2 что если class Collection2 : CollectionBase <Item2> ? (не проверял)
    3 может хотябы имена давать Collection1 - Items


  • отредактировано 04:06
    А как регистрируете коллекцию (или несколько коллекций?)
  • отредактировано 04:06
    AlexTZ написал: »
    А как регистрируете коллекцию (или несколько коллекций?)

    регистрирую коллекцию CompositeReportElement
  • отредактировано 04:06
    Я имел в виду - что передается в метод report.RegisterData? Покажите полный код.
  • отредактировано 04:06
    AlexTZ написал: »
    Я имел в виду - что передается в метод report.RegisterData? Покажите полный код.
    class CompositeReportElement
    {
    Collection1 Collection1 {get;}
    Collection2 Collection2 {get;}
    }
    ...
    data = new List<CompositeReportElement >()
    ...
    report.RegisterData(
    				data,
    				typeof(CompositeReportElement).GetAttribute<DisplayNameAttribute>().DisplayName,
    				BOConverterFlags.BrowsableOnly,
    				100); 
    
  • отредактировано 04:06
    Теперь проблема понятна. Я поменяю код так, чтобы создавалось два источника данных (Collection1Items, Collection2Items).
  • отредактировано 04:06
    AlexTZ написал: »
    Теперь проблема понятна. Я поменяю код так, чтобы создавалось два источника данных (Collection1Items, Collection2Items).

    а как будет алиас строиться?
    хотелось бы какой-нибудь разделитель желательно отличный от пробела так как алиас Collection1 может их уже содержать (у меня во всяком случае есть пара таких)
  • отредактировано 04:06
    Имя родительского св-ва + имя источника, без разделителей.
  • отредактировано 04:06
    AlexTZ написал: »
    Имя родительского св-ва + имя источника, без разделителей.

    вроде как не очень юзер френдли получается :-(
  • отредактировано 04:06
    Мне вообще нынешняя система не очень нравится, буду переделывать.
  • отредактировано 04:06
    в сборку 1.1.16.0 не попало?
  • отредактировано 04:06
    Я сейчас заканчиваю переделку работы с бизнес-объектами, сообщу, когда будет готово.

    Что будет нового:
    - при регистрации не нужно указывать параметр maxNestingLevel. Уровень вложенности может быть любым - в окне "Выбрать данные" можно развернуть столько уровней, сколько необходимо в данном отчете;
    - структура источника данных полностью повторяет структуру бизнес-объекта (Ваш случай - когда вложенный источник данных находится в промежуточном св-ве).

    Минусы: существующие отчеты, если в них используются вложенные источники, придется переделать.
  • отредактировано 04:06
    Отлично !!!
    с отчетами конечно хуже (около 20шт), хотя они щас в старом формате (Collection1.Items).

    Хорошо бы конечно еще и мастер для таких отчетов, т.е. несколько таблиц в одном отчете и к группировке добавить выбор тоталов
  • отредактировано 04:06
    Забыл отписаться здесь - новый движок готов, можно пробовать. Подробности здесь: http://fast-report.com/ru/forum/index.php?showtopic=6522
  • отредактировано 04:06
    Да спасибо уже пробую
    пока что System.StackOverflowException на некоторых очетах :-)
    пробую найти мин. код для повторения



  • отредактировано 04:06
    найти мин. код пока не смог, но ошибка возникает в след. случаях:

    1 report.RegisterData(IEnumerable, string)
    2 в дизайнере ставим галки на дата соурсах
    3 сохраняем отчет
    4 новый инстанс отчета
    5 грузим из сохраненого
    6 опять report.RegisterData(IEnumerable, string)
    StackOverflow

    или
    1 report.RegisterData(IEnumerable, string)
    2 в дизайнере ставим галки на дата соурсах
    3 превью (отчет вообще без полей)
    4 закрываем превью
    StackOverflow
  • отредактировано 04:06
    Нужен код бизнес-объекта, без этого ничего сказать не смогу.
  • отредактировано 04:06
    Нашел, проверял и наследование и шаблоны и циклические ссылки а все оказалось просто :-)
    public class Test
        {
            private DateTime _dateTime = DateTime.Today;
    
            public DateTime Date { get { return _dateTime; } }
        }
    
       report.RegisterData(new List<Test> {new Test()}, "test");
    

  • отредактировано 04:06
    Да, я это оказывается вчера пофиксил :) Ждите очередной сборки сегодня ночью.
  • отредактировано 04:06
    byte[] понимает как источник даных без полей а не как картинку
  • отредактировано 04:06
    Ок, исправлю.
  • отредактировано 04:06
    Подвал данных не подвязывает данные с бизнес обьектов
  • отредактировано 04:06
    В подвале данных нельзя обращаться к источнику данных - в этот момент он находится в состоянии EOF.
  • отредактировано 04:06
    AlexTZ написал: »
    В подвале данных нельзя обращаться к источнику данных - в этот момент он находится в состоянии EOF.

    спасибо, разобрался

Оставить комментарий

Многофункциональный текстовый редактор. Чтобы отредактировать стиль параграфа, нажмите TAB, чтобы перейти к меню абзаца. Там вы можете выбрать стиль. По умолчанию не выбран ни один стиль. Когда вы выберете текст, появится встроенное меню форматирования. Нажмите TAB, чтобы войти в него. Некоторые элементы, такие как многофункциональные вставки ссылок, картинок, индикаторов загрузки и сообщений об ошибок могут быть вставлены в редактор. Вы можете перемещаться по ним, используя стрелки внутри редактора и удалять с помощью клавиш delete или backspace.