Присоединяюсь к xokc. Если надо просто обнулить время то таки да - DateOf
» Использование DevExpress
В приложении все действия выполняются через TAction.
TAction сгруппированы в разные TActionList'ы.
Использую TdxBarManager.
В каждый момент времени активен "общий" TActionList (TdxBar соответствует MainMenu) и д.б. активен только один "дополнительный" TActionList.
Соответственно, хочется иметь отдельный TdxBar соответствующий дополнительному TActionList'у.
Как лучше сделать?
Если иметь много дополнительных dxBar'ов и управять их Visible - прыгает размер самого менеджера (1<->2 строки) - некрасиво.
Иметь один dxBar и управлять видимостью кнопок - просто неудобно.
Как лучше сделать?
TAction сгруппированы в разные TActionList'ы.
Использую TdxBarManager.
В каждый момент времени активен "общий" TActionList (TdxBar соответствует MainMenu) и д.б. активен только один "дополнительный" TActionList.
Соответственно, хочется иметь отдельный TdxBar соответствующий дополнительному TActionList'у.
Как лучше сделать?
Если иметь много дополнительных dxBar'ов и управять их Visible - прыгает размер самого менеджера (1<->2 строки) - некрасиво.
Иметь один dxBar и управлять видимостью кнопок - просто неудобно.
Как лучше сделать?
Такс.. то ли торможу то ли лыжи не едут. Задача - в гриде при изменении значения одной колонки (дата начала периода) автоматом выставлять значение в соседней колонке (дата окончания периода). Делаю следующим образом в обработчике OnEditValueChanged первой колонки:
Код:
with tvMyView.DataController do
begin
if ([dceInsert] <= EditState) then
begin
Values[FocusedRecordIndex,
TcxGridDBTableView(GridView).GetColumnByFieldName('ENDDATE').Index] :=
DateOf(TcxDateEdit(Sender).EditValue) + 1;
end;
end;
Код:
with tvMyView.DataController do
begin
if ([dceInsert] <= EditState) then
begin
Values[FocusedRecordIndex,
TcxGridDBTableView(GridView).GetColumnByFieldName('ENDDATE').Index] :=
DateOf(TcxDateEdit(Sender).EditValue) + 1;
end;
end;
golkanavt
Вот пример с сайта, ссылку не помню.
// Delphi code
uses
cxVariants, cxDataUtils;
procedure <Form>.<Column>PropertiesEditValueChanged(
Sender: TObject);
var
Edit: TcxCustomEdit;
Value: Double;
View: TcxGridDBTableView;
AnotherColumn: TcxGridColumn;
begin
Edit := Sender as TcxCustomEdit;
if VarIsNumericEx(Edit.EditValue) then
begin
Value := Edit.EditValue;
Edit.PostEditValue; // To 'stick' the new value in the active cell
View := <Grid>.FocusedView as TcxGridDBTableView;
AnotherColumn := View.GetColumnByFieldName(AnotherField);
View.DataController.SetEditValue(AnotherColumn.Index, Value/5, evsValue);
end;
end;
Вот пример с сайта, ссылку не помню.
// Delphi code
uses
cxVariants, cxDataUtils;
procedure <Form>.<Column>PropertiesEditValueChanged(
Sender: TObject);
var
Edit: TcxCustomEdit;
Value: Double;
View: TcxGridDBTableView;
AnotherColumn: TcxGridColumn;
begin
Edit := Sender as TcxCustomEdit;
if VarIsNumericEx(Edit.EditValue) then
begin
Value := Edit.EditValue;
Edit.PostEditValue; // To 'stick' the new value in the active cell
View := <Grid>.FocusedView as TcxGridDBTableView;
AnotherColumn := View.GetColumnByFieldName(AnotherField);
View.DataController.SetEditValue(AnotherColumn.Index, Value/5, evsValue);
end;
end;
jicoff
отлично, спасибо за наводку.. значит, все дело в волшебных пузырьках, т.е. PostEditValue и SetEditValue
отлично, спасибо за наводку.. значит, все дело в волшебных пузырьках, т.е. PostEditValue и SetEditValue
Не подскажет ли кто, как в cxGrid прочитать значение FooterSummary конкретной колонки?
Bill_PHO
Цитата:
<Grid>.FocusedView.DataController.Summary.FooterSummaryItems;
Цитата:
Не подскажет ли кто, как в cxGrid прочитать значение FooterSummary конкретной колонки?
<Grid>.FocusedView.DataController.Summary.FooterSummaryItems;
golkanavt
Спасибо.
Добавлено:
golkanavt
Цитата:
А как это будет выглядеть для конкретной колонки?
Добавлено:
golkanavt
Получилось так:
Grid>.FocusedView.DataController.Summary.FooterSummaryValues[0];
Спасибо за наводку.
Спасибо.
Добавлено:
golkanavt
Цитата:
Grid>.FocusedView.DataController.Summary.FooterSummaryItems;
А как это будет выглядеть для конкретной колонки?
Добавлено:
golkanavt
Получилось так:
Grid>.FocusedView.DataController.Summary.FooterSummaryValues[0];
Спасибо за наводку.
Bill_PHO
Вообще-то для связи с колонкой существует
FocusedView.DataController.Summary.FooterSummaryItems[i].ItemLink.
Если элементов много, то можно пройтись по всему списку и проверить на равенство ItemLink и указателя на конкретную колонку.
Вообще-то для связи с колонкой существует
FocusedView.DataController.Summary.FooterSummaryItems[i].ItemLink.
Если элементов много, то можно пройтись по всему списку и проверить на равенство ItemLink и указателя на конкретную колонку.
jicoff
Тоже полезно для меня.
Спасибо.
Тоже полезно для меня.
Спасибо.
подскажите как в cxGrid обработать MultiSelect.
Задача - берем и перетягиваем ДрагЭндДропом записи в другое место, они должны как то обработаться. С одной записью - сделал. а с кучей?
Задача - берем и перетягиваем ДрагЭндДропом записи в другое место, они должны как то обработаться. С одной записью - сделал. а с кучей?
yuish, перебираем SelectedRecords, получаем их индексы (В гриде), с помощью GetRecordByID (см. help) получаем табличные индексы. Дальше с помощью "теневой" таблицы ворочаем записи.
Стоит задача в ячейке грида отображать кнопку. ButtonEdit выглядит убого и неубедительно, хотя на крайний случай сойдет - но как тогда кнопку растянуть на всю ячейку?
golkanavt
Посмотри на сайте разработчиков, там что-то было на тему вставить свой контрол в качестве редактора. Может удастся другую кнопку подсунуть.
Посмотри на сайте разработчиков, там что-то было на тему вставить свой контрол в качестве редактора. Может удастся другую кнопку подсунуть.
Есть TcxDBTreeList.
Есть кнопка добавления записи которая делает Insert в таблицу на которой висит TcxDBTreeList.
Как сделать так, что бы добавляемое поле НЕ становилось ROOT для всех записей?
Есть кнопка добавления записи которая делает Insert в таблицу на которой висит TcxDBTreeList.
Как сделать так, что бы добавляемое поле НЕ становилось ROOT для всех записей?
Daeron
Так значения в KeyField и ParentField надо выставлять сразу, а то они, наверное, NULL, вот встают вначало.
Так значения в KeyField и ParentField надо выставлять сразу, а то они, наверное, NULL, вот встают вначало.
Сразу где?
В СУБД - не понятно как. До .Append - тоже неясно, делаю AfterInsert - поздно, запись становится корневой для всех.
Пытался делать что-то по типу .FullRefresh; - пропадает запись вообще.
В СУБД - не понятно как. До .Append - тоже неясно, делаю AfterInsert - поздно, запись становится корневой для всех.
Пытался делать что-то по типу .FullRefresh; - пропадает запись вообще.
Daeron
В событии OnNewRecord - если есть такое в твоей СУБД.
В событии OnNewRecord - если есть такое в твоей СУБД.
Для себя решил проблему так (правдо у меня источник через ADOData Set):
cxDBTreeList1.DataController.Insert;
cxDBTreeList1.DataController.DataSource.DataSet.FieldByName('NODE').Value:=NewVal;
cxDBTreeList1.DataController.Post;
при таком решении всё вставляется в "фокус". Конечно, должны быть указаны поля KeyField и ParentField.
cxDBTreeList1.DataController.Insert;
cxDBTreeList1.DataController.DataSource.DataSet.FieldByName('NODE').Value:=NewVal;
cxDBTreeList1.DataController.Post;
при таком решении всё вставляется в "фокус". Конечно, должны быть указаны поля KeyField и ParentField.
unfreqient
У такого решения есть одна проблема: необходимо знать значение нового идентификатора, а без обращения к базе никак его не получить. К тому же есть еще проблема, в многопользовательском режиме не совсем ясно, даже при обращении к базе, как его получить.
Есть конечно решение, например, выяснить максимальное значение ключа из датасета, на всякий случай прибавить константу, скажем 1000, далее как предлогает unfreqient, а там в зависимости от ситуации: получить значение и подправить поле.
Сам предпочитаю модальный диалог, даже если в дереве нужно только название узла вставить.
У такого решения есть одна проблема: необходимо знать значение нового идентификатора, а без обращения к базе никак его не получить. К тому же есть еще проблема, в многопользовательском режиме не совсем ясно, даже при обращении к базе, как его получить.
Есть конечно решение, например, выяснить максимальное значение ключа из датасета, на всякий случай прибавить константу, скажем 1000, далее как предлогает unfreqient, а там в зависимости от ситуации: получить значение и подправить поле.
Сам предпочитаю модальный диалог, даже если в дереве нужно только название узла вставить.
hobest
Цитата:
Это зависит от того какая у тебя база и что у тебя за идентификатор
В БД в которых есть sequnce (Oracle, Interbase (Firebird) и т.п.) , берем следующее значение из этого sequence. Изпользовать max - потенциальный сточник граблей при многопользовательской работе. Вот тут поднял проект - как раз добавление в дереве как потомок если установлено FAsChild:=True. Соответсвенно на датасет вешается два обработчика
var
FAsChild: boolean; // для добавления деревьев
procedure TdmMain.fdsTreeBeforeInsert(DataSet: TDataSet);
begin
IF DataSet.REcordCount<>0 then
begin
FID_Tree:= DataSet.FieldValues['ID'];
if not DataSet.FieldByName('ID_PARENT').IsNull then
FID_PARENT:=DataSet.FieldValues['ID_PARENT']
else
FID_PARENT:=0;
end
else
begin
FID_TREE:= 0;
FID_PARENT:=0;
end;
end;
//------------------------------------------------------------------------------
procedure TdmMain.fdsTreeNewRecord(DataSet: TDataSet);
begin
if FAsChild then
begin
if FID_TRee<>0 then DataSet.FieldValues['ID_PARENT']:=FID_TREE;
end
else
if FID_PARENT<>0 then DataSet.FieldValues['ID_PARENT'] := FID_PARENT;
end;
Добавлено:
hobest
Цитата:
Для MSSQL тоже можно извернуться и получить значение identy, но здесь врать не буду, потому как не помню.
На крайний случай всегда можно испольовать GUID
Цитата:
У такого решения есть одна проблема: необходимо знать значение нового идентификатора, а без обращения к базе никак его не получить. К тому же есть еще проблема, в многопользовательском режиме не совсем ясно, даже при обращении к базе, как его получить.
Это зависит от того какая у тебя база и что у тебя за идентификатор
В БД в которых есть sequnce (Oracle, Interbase (Firebird) и т.п.) , берем следующее значение из этого sequence. Изпользовать max - потенциальный сточник граблей при многопользовательской работе. Вот тут поднял проект - как раз добавление в дереве как потомок если установлено FAsChild:=True. Соответсвенно на датасет вешается два обработчика
var
FAsChild: boolean; // для добавления деревьев
procedure TdmMain.fdsTreeBeforeInsert(DataSet: TDataSet);
begin
IF DataSet.REcordCount<>0 then
begin
FID_Tree:= DataSet.FieldValues['ID'];
if not DataSet.FieldByName('ID_PARENT').IsNull then
FID_PARENT:=DataSet.FieldValues['ID_PARENT']
else
FID_PARENT:=0;
end
else
begin
FID_TREE:= 0;
FID_PARENT:=0;
end;
end;
//------------------------------------------------------------------------------
procedure TdmMain.fdsTreeNewRecord(DataSet: TDataSet);
begin
if FAsChild then
begin
if FID_TRee<>0 then DataSet.FieldValues['ID_PARENT']:=FID_TREE;
end
else
if FID_PARENT<>0 then DataSet.FieldValues['ID_PARENT'] := FID_PARENT;
end;
Добавлено:
hobest
Цитата:
К тому же есть еще проблема, в многопользовательском режиме не совсем ясно, даже при обращении к базе, как его получить.
Для MSSQL тоже можно извернуться и получить значение identy, но здесь врать не буду, потому как не помню.
На крайний случай всегда можно испольовать GUID
TcxTextEdit & Punto Switcher
Заюзал TcxTextEdit в режиме
cxEdit.Properties.EchoMode:= eemPassword;
Punto Switcher перехватывает ввод и переводит на кирилик...
Как бы побороть это (в наследнике TcxTextEdit).
Заюзал TcxTextEdit в режиме
cxEdit.Properties.EchoMode:= eemPassword;
Punto Switcher перехватывает ввод и переводит на кирилик...
Как бы побороть это (в наследнике TcxTextEdit).
uranic2
В случае sequence может получиться большое количество дырок, просто потому что пользователь может всегда отказаться от вставки новой записи - взял и передумал. Возможно это не так уж и плохо, но все зависит от ситуации. А как быть с MSSQL? Работа с guid не всегда удобна.
Похоже ты не внимательно читал сообщение hobest. Прибавление константы нужно только на момент вставки записи, пока еще не вызван Post. Это значение не предполагается отсылать на сервер, зато не будет лишнего обращения к БД. Особенно это касается auto increment полей, хотя бы того же MSSQL, для которых не предполагается резервирования значения, как это делает sequence. Думаю такой подход интересный и им вполне можно пользоваться.
В случае sequence может получиться большое количество дырок, просто потому что пользователь может всегда отказаться от вставки новой записи - взял и передумал. Возможно это не так уж и плохо, но все зависит от ситуации. А как быть с MSSQL? Работа с guid не всегда удобна.
Похоже ты не внимательно читал сообщение hobest. Прибавление константы нужно только на момент вставки записи, пока еще не вызван Post. Это значение не предполагается отсылать на сервер, зато не будет лишнего обращения к БД. Особенно это касается auto increment полей, хотя бы того же MSSQL, для которых не предполагается резервирования значения, как это делает sequence. Думаю такой подход интересный и им вполне можно пользоваться.
jicoff
Цитата:
Ох, с MSSQL я завязал 3 года назад, тут уж серьезно посоветовать не смогу. Для MSSQL
можно было писать процедуру и select @@identy - кажется так.
Цитата:
Каюсь, красаты идеи понял не сразу.
Цитата:
А как быть с MSSQL? Работа с guid не всегда удобна.
Ох, с MSSQL я завязал 3 года назад, тут уж серьезно посоветовать не смогу. Для MSSQL
можно было писать процедуру и select @@identy - кажется так.
Цитата:
Похоже ты не внимательно читал сообщение hobest. Прибавление константы нужно только на момент вставки записи
Каюсь, красаты идеи понял не сразу.
Цитата:
TcxTextEdit & Punto Switcher
Пока поборол так:
Отрезал на время ввода пароля виндовые события WMGetText, WMSetText, WMCopy, WMCut.
[more]
uses
...
cxEdit, cxTextEdit;
TcxTextEdit = class(cxTextEdit.TcxTextEditFxt)
protected
fInternalProtected: Boolean;
procedure WMGetText(var Message: TWMGetText); message WM_GETTEXT;
procedure WMSetText(var Message: TWMSetText); message WM_SETTEXT;
procedure WMGetTextLength(var Message: TWMGetTextLength); message WM_GETTEXTLENGTH;
procedure WMCopy(var Message: TMessage); message WM_COPY;
procedure WMCut(var Message: TMessage); message WM_CUT;
procedure WMPaste(var Message: TMessage); message WM_PASTE;
end;
TLogonForm = class(TForm)
...
end;
...
implementation
...
procedure ...Logon();
begin
...
EOldPwd.Properties.PasswordChar := '*';
EOldPwd.Properties.EchoMode:= eemPassword;
EOldPwd.fInternalProtected := True;
ENewPwd.Properties.PasswordChar := '*';
ENewPwd.Properties.EchoMode:= eemPassword;
ENewPwd.fInternalProtected := True;
EVerifyPwd.Properties.PasswordChar := '*';
EVerifyPwd.Properties.EchoMode:= eemPassword;
EVerifyPwd.fInternalProtected := True;
...
if ShowModal = mrOK then
begin
...
EOldPwd.fInternalProtected := False;
ENewPwd.fInternalProtected := False;
EVerifyPwd.fInternalProtected := False;
...
if AnsiCompareText(EOldPwd.Text, ENewPwd.Text) = 0 then
DLG_LOGON_ERROR('Новый пароль должен отличаться от старого');
...
procedure TcxTextEdit.WMGetText(var Message: TWMGetText);
begin
if fInternalProtected then
Message.Result := 0
else
inherited;
end;
procedure TcxTextEdit.WMSetText(var Message: TWMSetText);
begin
if fInternalProtected then
Message.Result := 0
else
inherited;
end;
procedure TcxTextEdit.WMGetTextLength(var Message: TWMGetTextLength);
begin
if fInternalProtected then
Message.Result := 0
else
inherited;
end;
procedure TcxTextEdit.WMCopy(var Message: TMessage);
begin
if Properties.EchoMode <> eemPassword then
inherited;
end;
procedure TcxTextEdit.WMCut(var Message: TMessage);
begin
if Properties.EchoMode <> eemPassword then
inherited;
end;
procedure TcxTextEdit.WMPaste(var Message: TMessage);
begin
//if Properties.EchoMode <> eemPassword then
inherited;
end;
[/more]
Добавлено:
hobest
Цитата:
mssql sequence
Можно sequence эмулировать через таблицу
tbl_sequence
seq_table varchar(60),
seq_value number(15)
Недостаток - нужен отдельный коннект для получения ключа.
Второй вариант - после коннекта получить диапазон генерации ключа (min, max). Недостаток - нужно менеджерить диапазоны ...
Третий вариант - генерация ключа на клиенте с использованиет уникального среза (IDLevel) выданного сервером БД.
При логоне приложение запрашивает свой уникальный срез:
procedure ...AfterConnected(
begin
IDLevel := ... // запросить уникальный срез
end;
Ключи генерим например по следующему алгоритму:
var
IDLevel: integer = 0; // счётчик на сервере БД (например дескриптор текущей сессии или ключ в привязке к пользователю)
LocalId: integer = 0; // локальный счётчик
function GetNowKey(): string;
begin
inc(local_id);
Result := FormatDateTime('yymmdd', Now) + IntToStr(IDLevel) + IntToStr(LocalId);
end;
Если IDLevel привязать к пользователю ,тогда нужно рассмотреть вариант одновременной работы нескольких приложений.
Дата время в ключе дадут возможность фильтровать по времени вставки.
Недостаток - длина ключа. 4 + 9 + 9 = 22 символа, т.е. number(22) == TBCD.
VadimLou
Думаю, что все эти решения "тяжеловесные", так и компонент TcxDBTreeList не захочешь использовать. Впрочем каждый решает для себя сам.
Думаю, что все эти решения "тяжеловесные", так и компонент TcxDBTreeList не захочешь использовать. Впрочем каждый решает для себя сам.
Alex1978
Цитата:
В оракле кажись нету. А постить в БД - некошерно, другой юзверь увидит, держать открытой транзакцию - зло.
Цитата:
В событии OnNewRecord - если есть такое в твоей СУБД.
В оракле кажись нету. А постить в БД - некошерно, другой юзверь увидит, держать открытой транзакцию - зло.
Daeron
[q][/q]
<TcxCustomDBTreeList.OnInitInsertingRecord>
Occurs before a node is inserted into the TreeList control.
type
TcxDBTreeListInitInsertingRecordEvent = procedure(Sender: TObject; AFocusedNode: TcxTreeListDataNode; var AHandled: Boolean) of object;
property OnInitInsertingRecord: TcxDBTreeListInitInsertingRecordEvent;
Description
The OnInitInsertingRecord event is fired before the end user inserts a node into the TreeList control. The AFocusedNode parameter identifies the inserted node. The AHandled parameter specifies whether the default handling is required. Set it to True to prevent the default handling.
Handle this event to calculate the ParentField value for the inserted record (since it is not implemented automatically).
[q][/q]
<TcxCustomDBTreeList.OnInitInsertingRecord>
Occurs before a node is inserted into the TreeList control.
type
TcxDBTreeListInitInsertingRecordEvent = procedure(Sender: TObject; AFocusedNode: TcxTreeListDataNode; var AHandled: Boolean) of object;
property OnInitInsertingRecord: TcxDBTreeListInitInsertingRecordEvent;
Description
The OnInitInsertingRecord event is fired before the end user inserts a node into the TreeList control. The AFocusedNode parameter identifies the inserted node. The AHandled parameter specifies whether the default handling is required. Set it to True to prevent the default handling.
Handle this event to calculate the ParentField value for the inserted record (since it is not implemented automatically).
Сталкивался ли кто с задачей блокировки дочерних записей в Detail View в зависимости от условия по данным в Master View? Блокировка нужна только для дочерних записей определенного родителя а не для всех "дочек".
golkanavt
Цитата:
А это что за "зверь" такой? В GridView есть такое понятие?
Цитата:
... блокировки дочерних записей ...
А это что за "зверь" такой? В GridView есть такое понятие?
Страницы: 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
Предыдущая тема: Kylix
Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.