21.02.2003, 11:00 | #1 |
Moderator
|
Гибрид FormTableControl и FormDataSource
Цитата:
Изначально опубликованно Maxim Gorbunov
Почему бы не написать класс, который бы цеплялся к FormDataSource и FormTableControl (ну, соответственно во всех обработчиках событий вызывать методы класса), а в нем уже управлять заполнением таблицы? При высоких (здесь не спорю) трудозатратах на программирование получаем очевидное преимущество в виде достаточно гибкого (по крайней мере по сравнению с Grid) в настройке контрола для отображения данных. Сразу говорю, что сам такое делать не буду, ибо времени нет Идею отдаю бесплатно (да и не нова она). 1. Отображать содержимое FormDataSource 2. Отображать ResultSet Нас интересует первый пункт или второй ? Или оба сразу ? Тогда это наверное должны быть две разных задачи. Рассмотим оба варианта: 1. FormTableControl, отображающий содержимое FormDataSource. Какие мы преимущества получаем по сравнению с использованием стандартного грида ? Возможность очень гибкого обращения с каждой ячейкой. Вот пожалуй и все. Или я что-то не улавливаю ? Хотя, как я понял речь, речь шла именно об этом варианте. 2. FormTableControl, умеющий ResultSet, как результат выполнения Statement. В этом случае мы получаем возможность сделать то, что вообще не реализованно в Аксапте, а именно сделать ЛЮБОЙ запрос на SQL Server (с какими угодно наворотами, не поддерживаемыми Аксаптой) и полученный результат отобразить виде таблицы. Итак, сначала давай решим, какую из этих задач мы решаем. Вопрос второй - концептуальный - как все это реализовать. Если бы я программировал на обычном языке программирования, я бы сделал следующее: создал наследника от FormTableControl, добавил бы ему свойство типа FormDataSource и переписал бы методы отвечающие за его отображение и редактирование. Но Аксапта не обычный язык рограммирования, поэтому этот способ здеь не пойдет. Если наследника FormTableControl я создать еще могу: class dem_Table extends FormTableControl { } то поместить его как компонент на форму практически не возможно. Или кто-то знает такой способ ? Значит надо делать как-то по другому. Например, это должен быть отдельный класс, имеющий свойства типа FormTableControl и FormDataSource. Во всех обработчиках событий FormTableControl будут вызываться методы этого класса, которые, в свою очередь будут обращаться к FormDataSource. Не совсем изящная конструкция, но более удачного решения я пока не вижу. Может есть еще варианты ? |
|
21.02.2003, 11:33 | #2 |
Administrator
|
Re: Гибрид FormTableControl и FormDataSource
Цитата:
Изначально опубликовано Андре
ОК. Для начала давай определимся с тем, что мы хотим получить. ... Нас интересует первый пункт или второй ? Или оба сразу ? Тогда это наверное должны быть две разных задачи. Цитата:
Изначально опубликовано Андре
Какие мы преимущества получаем по сравнению с использованием стандартного грида ? Возможность очень гибкого обращения с каждой ячейкой. Вот пожалуй и все.
Цитата:
Изначально опубликовано Андре
Вопрос второй - концептуальный - как все это реализовать. ... Например, это должен быть отдельный класс, имеющий свойства типа FormTableControl и FormDataSource. ... Не совсем изящная конструкция, но более удачного решения я пока не вижу. Может есть еще варианты ?
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
21.02.2003, 12:20 | #3 |
Moderator
|
Цитата:
Причем вторая - гораздо более трудоемкая, чем первая.
Цитата:
Поэтому предлагаю, решая первую, выявить все подводные камни и затем, в случае успешного решения, думать о реализации второй.
Тогда решим, что у нас в результате должно получится. За аналог возьмем Аксаптовский грид и попробуем описать, чем он будет от него отличаться а в чем совподать. То есть: 1. Загрузка данных в таблицу. Честно говоря, мне не совсем понятно, как это будет выглядеть. Как я понимаю, Аксапта использует серверные курсоры, то есть, на сервер посылается запрос но результат возвращается не весь, а небольшими порциями, в зависимости от того, что видит пользователь. Как это будет реализовано в нашем случае - мы будем моделировать аналогичное поведение или будем затягивать весь набор данных сразу на клиент ? В первом случае, нам придется перехватывать и обрабатывать все действия пользователя с нашей таблицей - скроллинг, фильтрацию, поиск. Во-втором случае все гораздо проще, но мы создаем неоправданную нагрузку на сеть. 2. Таблица будет только отображать данные или также позволит редактировать записи ? Добавлять записи ? Тоже есть ряд тонких моментов. Не совсем понятно, как это будет делаться в случае сложных датасоурсов, ну ладно, надеюсь по ходу дела пойму 3. Фильтрация 4. Поиск Как я понимаю, таблица должна будет поддреживать все эти вещи. Фильтровать и искать будем на клиенте или на сервере ? Это имеет отношение к пункту первому. |
|
21.02.2003, 12:37 | #4 |
Administrator
|
Цитата:
Изначально опубликовано Андре
Мне показалось как раз наоборот. Наверное я просто не вижу всех сложностей второго варианта. Цитата:
Изначально опубликовано Андре
Тогда решим, что у нас в результате должно получится. ... Загрузка данных в таблицу. ... Как я понимаю, Аксапта использует серверные курсоры, то есть, на сервер посылается запрос но результат возвращается не весь, а небольшими порциями, в зависимости от того, что видит пользователь. Как это будет реализовано в нашем случае - мы будем моделировать аналогичное поведение или будем затягивать весь набор данных сразу на клиент ? Цитата:
Изначально опубликовано Андре
В первом случае, нам придется перехватывать и обрабатывать все действия пользователя с нашей таблицей - скроллинг, фильтрацию, поиск. Цитата:
Изначально опубликовано Андре
Таблица будет только отображать данные или также позволит редактировать записи ? Добавлять записи ? Тоже есть ряд тонких моментов. Не совсем понятно, как это будет делаться в случае сложных датасоурсов, ну ладно, надеюсь по ходу дела пойму Цитата:
Изначально опубликовано Андре
3. Фильтрация 4. Поиск ... Фильтровать и искать будем на клиенте или на сервере ?
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
21.02.2003, 12:48 | #5 |
Administrator
|
Тут сейчас с InventTable копаюсь. Что-то подумалось, что была бы интересной возможность добавления в TableControl налету (то есть прямо пользователем) колонок из FormDataSource привязанного. А то не очень приятно, когда на Tab'е Обзор ты видишь только те колонки, которые кто-то определил важными.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
21.02.2003, 13:30 | #6 |
Moderator
|
Цитата:
В первом случае, нам придется перехватывать и обрабатывать все действия пользователя с нашей таблицей - скроллинг, фильтрацию, поиск.
Цитата:
Да, придется. ИМХО, сложностей возникнуть не должно, так как фактически должна получится тонкая прослойка между FormTableControl и FormDataSource.
PHP код:
Мы должны: 1. Добавить еще одну строку в Table 2. Прочитать из источника данных еще значений 3. Отобразить их в нашей таблице 4. Если это необходимо перейти к пункту 1. Во-первых как мы может отловить момент скролированния таблицы. Единственное, чего мне удалось добиться это textChange у StringEdit'а вложенного в Table. В нем нужно отрабатывать вышеописанный алгоритм ? Или есть более простой способ, которого я не вижу ? P.S. И еще, я вспомнил про лукапы. Как их будем делать ? |
|
21.02.2003, 14:27 | #7 |
Administrator
|
Цитата:
Изначально опубликовано Андре
Смотри. Пользователь открывает форму, на нем расположен наш Table, в нем видно 10 записей. Ну мы и отображаем 10 записей, примерно так: Цитата:
Изначально опубликовано Андре
Во-первых как мы может отловить момент скролированния таблицы. Цитата:
Изначально опубликовано Андре
Единственное, чего мне удалось добиться это textChange у StringEdit'а вложенного в Table. Цитата:
Изначально опубликовано Андре
P.S. И еще, я вспомнил про лукапы. Как их будем делать ?
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
21.02.2003, 14:33 | #8 |
Administrator
|
Есть идея. Заполнить cells чем-нибудь таким, что мы будем считать признаком "Не считано". Потом повесится на textChange и по мере поступления таких cell'ов читать их через DataSource. Как? Конечно, красоты мало в таком подходе, но у нас и средств не много...
Кстати, а ты пробовал addControl делать в динамике, а потом ему textChanged переопределять?
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
21.02.2003, 14:40 | #9 |
Moderator
|
Цитата:
Есть идея. Заполнить cells чем-нибудь таким, что мы будем считать признаком "Не считано". Потом повесится на textChange и по мере поступления таких cell'ов читать их через DataSource. Как? Конечно, красоты мало в таком подходе, но у нас и средств не много...
Цитата:
Кстати, а ты пробовал addControl делать в динамике, а потом ему textChanged переопределять?
|
|
21.02.2003, 15:56 | #10 |
Moderator
|
Ну я и торможу. Только сейчас увидел, что у каждого конторла в Table есть свойства DataSource и DataField, и то лишь когда увидел, что есть метод - addDataField.
Правда добиться корректной работы мне пока не удалось, отображается только активная запись, та на которой курсор - так и положено или я что-то не так делаю ? Насчет динамического добавления полей есть еще одна тонкость, при добавлении полей необходимо перекрывать метод editControl у Table. Буду разбираться. |
|
21.02.2003, 16:22 | #11 |
Administrator
|
Цитата:
Изначально опубликовано Андре
Ну я и торможу. Только сейчас увидел, что у каждого конторла в Table есть свойства DataSource и DataField, и то лишь когда увидел, что есть метод - addDataField. Цитата:
Изначально опубликовано Андре
Насчет динамического добавления полей есть еще одна тонкость, при добавлении полей необходимо перекрывать метод editControl у Table. Основная проблема на данный момент - понять, какие ячейки выводятся, а какие нет. Как это делать, я пока не понял. Задал вопрос на TechNet, может повезет. Кстати, по поводу наследования. Возникла бредовая идея разобраться с FormBuildTableControl и FormTableControl. Может удастся чего-нить понаследовать. Вообще, не хотелось бы отказываться от FormTableControl, но все на черный день у нас и FormWindowControl есть.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
25.02.2003, 08:45 | #12 |
Moderator
|
Итак, что я посмотрел, как обстоит дело с динамическим добавлением контролов в таблицу.
Задача делится на две подзадачи: а) определение количества и типов столбцов (как я понимаю информация будет браться из FormDataSource) б) динамическое добавление этих столбцов в FormTableControl Как я понимаю, пункт а) не представляет большой сложности (хотя я могу и ошибаться), так что насчет пункта б): Вот я набросал одну формочку - на ней Table и две кнопки. При нажатии на одну из них в таблицу добавляется поле целого типа, при нажатии на другую - в таблицу добавляется поле типа Data. Естественно типов может быть и больше. Несколько замечаний: 1. В таблице в дизайнере необходимо первоначально создать хотя бы один контрол, иначе даже при добавлении контролов в run-time изменения не видны. Если ты знаешь как это побороть - скажи, я поправлю. 2. Так как невозможно создать массив объектов, приходится создавать эти объекты динамически, а для этого пришлось завести массив, в котором хранятся типы столбцов. Хотя тут можно будет реализовать и более удачную конструкцию типа контейнера или map'а. Далее насчет динамического перекрытия методов создаваемых контролов. Я там поэкспериментировал маленько: на форме есть метод createMessageHandler, в который мы передаем имя создаваемого метода и текст метода. Собственно сам createMessageHandler создает этот метод, который и будет обрабатывать требуемые события. Метод вызывается при добавлении в таблицу нового столбца, то есть нажатии на клавишу. Для реализации этого пришлось пойти на следующие допущения: 1. Ввести ситему именования создаваемых контролов (тип+номер столбца, например int2, date3), а следовательно и методов (int2_textChange) Недостаток этого подхода: при нажатии на клавишу - создается столбец в таблице, создается контрол в таблице, контрол привязывается к столбцу и даже создается обработчик для этого контрола. НО, чтобы этот обработчик заработал, надо открыть и закрыть форму. Именно поэтому, я и не стал писать код, удаляющий динамически созданный обработчик событий. Посмотри сам: открой в АОТ методы формы и запусти форму, понажимай на клавиши и увидишь, как в АОТ появляются методы. Но они пока не действуют. А теперь закрой форму, и снова запусти ее, НО не удаляя созданные методы. Теперь все работает. Хотя нет, написал и сам понял. Все нормально. Эти методы в форму у нас будет добавлять класс. Затем, и только затем, эта форма будет запускаться нашим классом, а по окончании ее работы, класс будет уничтожать созданные методы. В этом случае все будт работать. Но я еще не вижу все картины, поэтоиу не могу сказать, как делать лучше Что ты думаешь по этому поводу ? |
|
25.02.2003, 08:46 | #13 |
Moderator
|
Предыдущее сообщения я написал 23-го. А 24-го с утречка решил взгянуть на картину шире и понял, что не пока понимаю довольно важной вещи, без которой все предыдущие рассуждения могут не иметь смысла:
Каким образом в таблицу будут выбираться поля для отображения из датасоурса(ов) ??? Я вижу следующие варианты: 1. При загрузке формы(перед загрузкой формы) в таблице автоматически создаются контролы и к ним привязываются обработчики событий. Это то, над чем я экспериментировал вчера. Достоинства: при удачной реализации, минимум работы программиста, использующих этот проект. Недостатки(?): а каким образом программа автоматически поймет, какие поля вытягивать в таблицу ? Никаким. Значит программист должен как-то указать классу, создающему поля в таблице, какие именно из них он хочет в ней видеть. Каким образом он будет это делать ? У тебя уже есть какие-то идеи, или это пока что совершенно не продуманная область ? 2. Что-то типа wizard'а, который мы натравливаем на заданную форму. Он спрашивает про интересующие нас поля и генерит контролы в таблице и все необходимые обработчики методов. Недостаток: сгенерированную, таким образом форму в дальнейшем придется сопровождать "ручками", без участия нашего мастера. То есть, если в дальнейшем, в эту таблицу нужно будет вытащить еще один столбец, то либо программисту придется это делать ручками, либо наш мастер должен быть очень умным. 3. Все контролы в таблице создаются вручную программистом. Им же создаются все необходимые обработчики событий. Плюс: минимум работы с нашей стороны Минус: и кто же после этого будет этим пользоваться ? Ты задумывался над этим ? |
|
25.02.2003, 08:49 | #14 |
Moderator
|
Цитата:
Вообще, не хотелось бы отказываться от FormTableControl, но все на черный день у нас и FormWindowControl есть.
|
|
25.02.2003, 11:21 | #15 |
Administrator
|
Цитата:
Изначально опубликовано Андре
В таблице в дизайнере необходимо первоначально создать хотя бы один контрол, иначе даже при добавлении контролов в run-time изменения не видны. ... Далее насчет динамического перекрытия методов создаваемых контролов. Я там поэкспериментировал маленько: на форме есть метод createMessageHandler, ... НО, чтобы этот обработчик заработал, надо открыть и закрыть форму. ... Посмотри сам: открой в АОТ методы формы и запусти форму, понажимай на клавиши и увидишь, как в АОТ появляются методы. ... Что ты думаешь по этому поводу ? Цитата:
Изначально опубликовано Андре
Каким образом в таблицу будут выбираться поля для отображения из датасоурса(ов) ???
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
25.02.2003, 11:24 | #16 |
Moderator
|
Цитата:
Э-э... А можно форму-то посмотреть?
Цитата:
Если ты про то, каким образом выбирать поля для добавления, то я предлагаю... третий вариант.
|
|
25.02.2003, 11:31 | #17 |
Administrator
|
Цитата:
Изначально опубликовано Андре
Нет. Вопрос не как выбирать. Вернее не столько как выбирать, а как добавлять. Каким образом столбзы будут ДОБАВЛЯТЬСЯ в таблицу: динамически (прикремленный файл), мастер или пользователь (см. сообщение выше).
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
25.02.2003, 13:21 | #18 |
Moderator
|
Цитата:
Давай сделаем так (пока не знаю, какие проблемы возникнут - еще не посмотрел): пусть столбцы добавляются динамически, но добавление регулирет программист (скажем, какой-то метод вызывает).
|
|
26.02.2003, 12:49 | #19 |
Moderator
|
Времени мало, поэтому сделал не много. Здесь я приложил проект - там форма и класс запусай класс.
Несколько пояснений. Вот new() этого класса: PHP код:
Вот здесь: PHP код:
P.S. 1. Реализованно только для int, но это легко расширяется. 1а. Класс ищет именно таблицу с именем Table и именно в корне design. В будущем расширяемо. 2. В addColumn происходит перекрытие textChange() для добавляемого столбца. 3. Как я понимаю именно это ты имел в виду здесь : Цитата:
Давай сделаем так (пока не знаю, какие проблемы возникнут - еще не посмотрел): пусть столбцы добавляются динамически, но добавление регулирет программист (скажем, какой-то метод вызывает).
За всем этим делом лучше всего наблюдать так: открыть в отдельном окне форму, развернуть ветвь ее методов и контролов в Table и запустить класс. При этом форма откроется, а в АОТ'е будет видно, что в таблице создались контролы, а в форме соответствующие обработчики событий. После закрытия формы, в АОТ'е видно, что все созданное удалилось. Поиграйся(поскролируй) Table и ты увидишь, что для каждого столбца работает свой обработчик событий. Итог: мы напускаем класс на форму с Table, класс генерит в этом табле кучу всего, запускает форму, после ее закрытия все подчищяет за собой. Вроде как работает, но это пугает меня - самомодифицирующийся код никогда не отличался надежностью, легкостью сопровождения и отладки В общем посмотри проект и скажи что думаешь. |
|
27.02.2003, 09:51 | #20 |
Moderator
|
Отложим (на время) динамическое формирование таблицы и подумаем о том, как у нас эта самая таблица будет заполняться данными. Как мы решили, данные будут грузиться не сразу все, а по мере необходимости.
Максимально упростим пример. Вот форма, на ней таблица, в ней один столбец, в который должно выводиться itemId из invatTable, которое являетмся dataSource в этой форме. В executeQuery() мы определяем количество записей в таблице(забудем пока про производительность и оптимальность и попробуем просто понять принцип работы) и добавляем первые 20 записей в таблицу: PHP код:
PHP код:
Когда будешь пробовать попробуй сначала так, а затем раскомментировав сторки. Результаты чуть-чуть разные, но выводы примерно такие: Если мы хотим, чтобы textChange() вызывался со 100% гарантией пользователь должен щелкнуть мышкой на одну из ячеек таблицы и клавишами "стрелка вниз", PageDown перемещаться по таблице. Так вроде все работает. Если же пользователь начинает скролировать таблицу, то часто получается ситуация, когда пользователь начинает видеть пустые незаполненные строки.. в общем сам увидишь. Кроме того, textChange() будет вызываться даже тогда, когда пользователь начнет перемещаться по таблице вверх - вроде бы не надо, но в таблицу все равно будут добавляться новые записи. Можно сделать следующее(только что пришло в голову) - выбросить из таблицы скролбар(раз им все равно пользоваться нельзя), а в замен попробовать подсунуть пользователю что нибудь другое(в простейшем случае пару кнопок). Положение курсора в таблице тображать например с помощью progressBar'а. В общем все дело опять уходит в дебри и превращается в неудобную конструкцию. Буду дальше экспериментировать, но и ты скажи свое мнение, а то может я вообще не в том направлении двигаюсь и фигней занимаюсь ? |
|