Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Использование DevExpress (часть 3)

Автор: ATAWA
Дата сообщения: 24.06.2009 16:47
volser


Цитата:
ATAWA

Close/Open для ADOTable чем не устраивает?


В смысле программно делать Close/Open ADOTable перед каждой попыткой редактирования дерева пользователем?
Автор: Roma4ke
Дата сообщения: 24.06.2009 16:47
спасибо за совет. попробовал , OnInitEdit присваивает стиль , только когда произошло нажатие, а когда нет действий кнопики прежние.
Автор: volser
Дата сообщения: 24.06.2009 16:58
ATAWA

Цитата:
В смысле программно делать Close/Open ADOTable перед каждой попыткой редактирования дерева пользователем?


Не совсем так. Можно на форме сделать кнопку "Обновить данные" на клик которой переоткрывать набор данных. Если пользователь хочет увидеть изменения, то он нажимает на эту кнопку и получает новые данные.
Автор: jicoff
Дата сообщения: 24.06.2009 17:54
Roma4ke

А что такое
Цитата:
а то что cxGrid содержит колонку с кнопками не показыват


Т.е. в колонке выбран редактор TcxEditButtons, у которого много кнопок? Если так, то эти кнопки без Owner'а, и они не могут быть выбраны таким способом.
Автор: volser
Дата сообщения: 24.06.2009 18:08
Roma4ke

Цитата:
..а когда нет действий кнопики прежние.


Добавьте следующий код (пишу на Delphi)


Код:

type
TcxCustomGridTableItemWrapper = class(TcxCustomGridTableItem);

procedure TForm1.FormCreate(Sender: TObject);
begin
with TcxCustomGridTableItemWrapper(cxGrid1TableView1Column1) do begin
GetCellStyle.Assign(cxButtonEdit1.Style);
end;
end;

Автор: jicoff
Дата сообщения: 24.06.2009 18:08
Roma4ke

Кстати, если посмотреть переписку, откуда взят этот пример, то этот код так же не заработал. Далее дается ссылка на пример Example.zip, где предлогается использовать CustomDraw, это при поверхностном просмотре рекомендуемого кода, детально не изучал.
Автор: volser
Дата сообщения: 24.06.2009 18:14
jicoff


На CustomDraw у меня не совсем корректно работает отрисовка стиля.
Автор: Roma4ke
Дата сообщения: 24.06.2009 18:34
вствил такую строчку
TcxCustomGridTableItem(cxGrid1TableView1Column1).Styles->Assign(cxButtonEdit1->Style); - ничего не изменяется и вылетает ошибка , а функции GetCellStyle нету ((( . и я не понял зачем новый тип создавать ?
Автор: volser
Дата сообщения: 24.06.2009 19:02
Roma4ke

GetCellStyle - protected свойство, что бы оно было доступно нужно что бы тип был объявлен в это же юните. Для этого создается новый тип. Дальше нашу колонку нужно привести к этому типу.

У меня
Код: TcxCustomGridTableItemWrapper(cxGrid1TableView1Column1)
Автор: ATAWA
Дата сообщения: 25.06.2009 09:12
volser


Цитата:
Не совсем так. Можно на форме сделать кнопку "Обновить данные" на клик которой переоткрывать набор данных. Если пользователь хочет увидеть изменения, то он нажимает на эту кнопку и получает новые данные.


Да это не вопрос, такая кнопка давно есть.
Проблема в том, что не заставлю же я каждый раз пользователя нажимать эту кнопку перед, допустим, добавлением записи в дерево.
А получается, следующее: Если с одного клиента добавить запись в дерево и потом с другого клиента без реопена датасета добавлять запись на тот же уровень дерева, возникает ошибка уникальности по первичному ключу (ID+PARENT_ID) в таблице дерева. Как я понимаю, это происходит потому, что при добавлении записи DbTreeView не получает обновленные данные с сервера и, соответственно, не может правильно сгенерировать новый ID.
Или например, добавляет юзер подузел в дерево, а на другом клиенте перед этим родителя этого подузла удалили, после обновления (реопена датасета) добавленный подузел улетает в корень дерева, т.к. его PARENT_ID ссылается на несуществующий объект.
Мне сначала представлялось, что DbTreeView может оперативно видеть обновленные данные на серваке как-то обрабатывать такии коллизии, выходит что это не так
Получается надо вешать реопен всего датасета плюс писать соответствующие проверки на событие перед добавлением записи, но это как-то некрасиво, и долго если это будет очень большая таблица, был бы мягкий рефрешь какой-нибудь....
Ну или еще вариант, самому генерить новый ID, но это все равно только через селект к таблице дерева
Автор: f3ka
Дата сообщения: 25.06.2009 09:21
ATAWA
ну вообще то все проверки на существование родителя и получение значения нового ключа делаются непосредственно перед вставкой записи в БД... это может быть реализовано на клиенте или на сервере... если возникают какие то проблемы то пользователя необходимо оповестить об этом, но данные которые он вводил не потерять!
автоматического обновления данных просто так не добиться... в SDAC'e есть компонент для получения сообщений об изменении данных на сервере, но он работает с 2005 сервером... у FIB+ есть возможность отлавливать события сгенерированные в БД FireBird и InterBase... в ADO конечно же всего такого нету...
можно попробовать написать поток который бы мониторил изменения в таблице, по таймеру например... вариантов решения думаю можно еще накопать... тут дело в фантазии просто...
Автор: ATAWA
Дата сообщения: 25.06.2009 09:40
f3ka

Спасибо.
Я так приблизительно и предполагал.
Ну что-ж, будем фантазировать, копать и писать
Автор: SlavZa
Дата сообщения: 25.06.2009 10:10
f3ka
вот картинка, может будет понятней -

Автор: volser
Дата сообщения: 25.06.2009 10:32
ATAWA

Цитата:
Если с одного клиента добавить запись в дерево и потом с другого клиента без реопена датасета добавлять запись на тот же уровень дерева, возникает ошибка уникальности по первичному ключу (ID+PARENT_ID) в таблице дерева


А как это у вас так получается? Как генерируется айдишник? Какая структура таблицы?
Автор: ATAWA
Дата сообщения: 25.06.2009 11:25
volser

Цитата:
А как это у вас так получается? Как генерируется айдишник? Какая структура таблицы?


Так вот в том весь и фикс-пикус, что хотелось обойтись малой кровью используя связку DbTreeView и ADOTable, при этом все операции юзера в дереве DbTreeView САМ транслирует в БД (в том числе и генерацию ID он сам делает).
Но проблема в том что гладко это работает в однопользовательском варианте, а при многопользовательской работе встроенного функционала DbTreeView не хватает, чтобы обработать все коллизии.
Придется похоже дописывать самостоятельно.
п.с. Структура табицы классическая для дерева: ID, Parent_Id, Name...
Автор: volser
Дата сообщения: 25.06.2009 11:38
ATAWA

Если ID генерируется сиквенсом, то вы никак не получите ошибку уникальности ключа ID + PARENT_ID,
по этому я и спрашиваю как у вас генерируются ID?
Автор: ATAWA
Дата сообщения: 25.06.2009 12:26
volser


Цитата:
Если ID генерируется сиквенсом, то вы никак не получите ошибку уникальности ключа ID + PARENT_ID,
по этому я и спрашиваю как у вас генерируются ID?


Я же говорю, ID и ParentId генерируется встроенными механизмами DbTreeView (у него свойства есть ID и ParentId, на которые назначаются соответствующие поля моей таблицы).
Сиквенсов, триггеров и обработчиков в коде клиентского приложения поидее никаких нинадо, и поэтому я их и не делал изначально.
Я не лазил в код этих механизмов DbTreeView, но они не могут корректно сгенерить ID (NewKeyValue) при многопользовательской работе, возникает ошибка ключа по уникальному полю ID.
Сейчас я эту проблему в принципе уже решил, перехватывая событие OnCreateNewKeyValue DbTreeView и генерируя ID там самостоятельно.
Наверное помог бы и вариант сиквенс+триггер на серваке.
Просто изначально думалось, что DbTreeView сам справиться в сетевом варианте, как он справляется в локальном ан нет, отсюда и все мои вопросы...
Автор: jicoff
Дата сообщения: 25.06.2009 12:27
volser

Вообще-то вопрос резонный, зачем создавать новый стиль: GetCellStyle. Если у айтема не было стиля, то при вызове этого метода он создается. А нужно ли это, вопрос!
Автор: ecix
Дата сообщения: 25.06.2009 12:27
Пара вопросов для одной задачи:

1. Как можно перечислить строки в cxGrid в том порядке, в котором они отсортированы, включая те, которые не открыты (при группировке)? Они, как я понимаю, вообще не существуют пока пользователь не раскрыл соответствующую ветку.

2. Как можно отледить события сортировки или группировки колонок? Надо сделать некоторые манипуляции над строками, после того как их порядок изменился. События cxGrid.DataController.OnSortingChanged и OnGroupingChanged не вызываются после соответствующих действий (да и описаний их я нигде не нашел)

Автор: volser
Дата сообщения: 25.06.2009 12:37
ATAWA

Если посмотришь на код:

Код:
function TdxDBTreeView.GetNextMaxKeyValue: Variant;
begin
Result := DBTreeNodes.MaxKeyFieldValue;
if Assigned(FCreateNewKeyValue) then
FCreateNewKeyValue(nil, Result)
else
try
if not VarIsNULL(Result) then
Result := Result + 1
else
Result := 0;
except
end;
end;
Автор: vladman
Дата сообщения: 25.06.2009 13:00
ecix

Цитата:
Как можно отледить события сортировки или группировки колонок? ... События cxGrid.DataController.OnSortingChanged и OnGroupingChanged не вызываются

Именно этими событиями и можно отследить. Только что проверил - обрабатываются. Может у вас что-то специфическое? Давайте пример кода, попробуем разобраться.

Цитата:
да и описаний их я нигде не нашел

ms-help://borland.bds5/ExpressDataController.BDS5/ExpressDataController/IDH_TcxCustomDataController_OnGroupingChanged.htm
ms-help://borland.bds5/ExpressDataController.BDS5/ExpressDataController/IDH_TcxCustomDataController_OnSortingChanged.htm
Автор: Roma4ke
Дата сообщения: 25.06.2009 13:03
как реализовать на С++ ???
type (мой класс)TcxCustomGridTableItemWrapper = class(какойто классTcxCustomGridTableItem);
Автор: vladman
Дата сообщения: 25.06.2009 13:05
ecix

Цитата:
Как можно перечислить строки в cxGrid в том порядке...

Посмотреть в сторону TcxCustomDataController.ForEachRow
ms-help://borland.bds5/ExpressDataController.BDS5/ExpressDataController/IDH_TcxCustomDataController_ForEachRow.htm
Автор: f3ka
Дата сообщения: 25.06.2009 13:13
Roma4ke
ну наверно как то так

Код:
class TcxCustomGridTableItemWrapper: public TcxCustomGridTableItem
Автор: Roma4ke
Дата сообщения: 25.06.2009 13:19
volser
вроде сделал так :создал тип
typedef class TcxCustomGridTableItem TcxCustomGridTableItemWrapper;

TcxCustomGridTableItemWrapper(tvTestGoPaus).GetCellStyle->Assign(cxButtonEdit1->Style); -- но все равно GetCellStyle недоступен ((
Автор: volser
Дата сообщения: 25.06.2009 13:25
jicoff

Цитата:
Вообще-то вопрос резонный, зачем создавать новый стиль: GetCellStyle. Если у айтема не было стиля, то при вызове этого метода он создается. А нужно ли это, вопрос!


Где видно что я создаю новый стиль? Я вызываю метод получения текущего стиля. Сам стиль инициализируется намного раньше.

Roma4ke
Что это за переменная tvTestGoPaus?

Добавлено:
f3ka выше написал как нужно объявить класс.
Автор: Roma4ke
Дата сообщения: 25.06.2009 13:30
volser
tvTestGoPaus - имя TcxGridColumn.


class TcxCustomGridTableItemWrapper: public TcxCustomGridTableItem {};
выходит ошибка , которая говорит что не может сгенерировать стандартный конструктор, нужно еще как то конструкторы создать ((
Автор: volser
Дата сообщения: 25.06.2009 13:35
К сожалению с С++ не работаю. Для Delphi пример рабочий, проверял.
Автор: f3ka
Дата сообщения: 25.06.2009 13:43
Roma4ke
может тогда поучиться писать сначала какие то более простые вещи? это же основы основ... даже не знаю что еще сказать...
З.Ы. здесь топик то все таки по Delphi, а не C++
Автор: Roma4ke
Дата сообщения: 25.06.2009 13:47
(( и DevExpress походу все для делфи делали а не для с++ . в хелпе такой функции не нашел даже getcellstyle

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081

Предыдущая тема: Delphi: tcp клиент в потоке


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.