Поиск:

Ответ в темуСоздание новой темы Создание опроса
> OnValidate, для поля в таблице 
:(
    Опции темы
Inga
Дата 28.2.2006, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Подскажите, как правильно написать обработчик OnValidate для поля в таблице?
Например, поле имеет тип AsCurrency и содержит значения типа 78,53, а пользователь вводит туда ошибочно, например, дату типа 25.02.2006. Естественно при нажатии Enter возникает исключение. Как его правильно обработать в OnValidate поля, чтобы показать ShowMessage о некоренных данных и отменить ввод этих не правильных данных?
Cпасибо.


PM   Вверх
Vyacheslav
Дата 1.3.2006, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



OnValidate предназначен для обработки логических ошибок. Он бы подошел, например, если бы пользователь ввел 100, а по логике он должен ввести не более 50.
В вашем же случае имеется ошибка преобразования. Для ее обработки Вам надо воспользоваться
скорее всего событиями OnEditError или OnPostError
Код

typedef void __fastcall (__closure *TDataSetErrorEvent)(TDataSet* DataSet, EDatabaseError* E, TDataAction &Action);
__property TDataSetErrorEvent OnEditError = {read=FOnEditError, write=FOnEditError};


Кстати можно воспользоваться событием событием OnSetText для того чтобы отслеживать, что конкретно ввел пользователь


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Inga
Дата 1.3.2006, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



>надо воспользоваться скорее всего событиями OnEditError или OnPostError


Спасибо, буду пробывать.
PM   Вверх
Inga
Дата 6.3.2006, 23:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



>Кстати можно воспользоваться событием событием OnSetText для того чтобы отслеживать, что конкретно ввел пользователь


Пишу обработчик:
void __fastcall TForm1::Table1PriseSetText(TField *Sender,
const AnsiString Text)
{


Currency C;
try {
C = StrToCurr(Text);
}
catch(...)
{
ShowMessage("Не правильный ввод" + Text);
Abort();
}


}
Через буфер обмена вставляю в запись не правильную запись например 25.02.2006. Как я понимаю должен появиться ShowMessage, а я получаю исключение: 25.02.2006 is not a valid floating point value
Как правильно обработать вставку не верного значения в запись из буфера обмена?

PM   Вверх
Vyacheslav
Дата 7.3.2006, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Случайно, не в режиме отладки при запуске в IDE получаете это сообщение?


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Inga
Дата 7.3.2006, 10:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



>Случайно, не в режиме отладки при запуске в IDE получаете это сообщение?

Да, нажимаю кнопку компиляции и дальше в форме беру копирую из строки другого компонента значение 25.02.2006 и вставляю в грид. Значение вставляется. Нажимаю Enter и получаю исключение.
При попытки ввести не правильное значение в это поле с клавиатуры, не правильные символы игнорируются т.е. все нормально, а вот при вставке из буфера обмена получаю исключение. smile



PM   Вверх
Vyacheslav
Дата 7.3.2006, 11:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Так этож правильно. Вы дайте дальше программе поработать и получитете нужное сообщение. Это IDE так настроен у Вас, что бы показывать где и какое исключение возникнет вне зависимости есть перехват или нет далее по коду. Что бы понятно было, запустите Вашу программу не из IDE, и все будет работать так как Вы и предполагали smile
C праздником Вас.


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Inga
Дата 7.3.2006, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Ура! Работает (если запускать не из IDE). Два дня я мучилась – искала ошибку. Мне и в голову не приходило, что надо запустить без IDE.
Скажите, мой обработчик Table1PriseSetText полностью корректен? Может в catch надо передать что-то другое для надежности?

Большое спасибо за помощь и поздравления!

С уважением, Инга.

PM   Вверх
Vyacheslav
Дата 7.3.2006, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



В общем сойдет. Но с точки зрения правильности не стоит использовать конструкцию cath(...). Лучше указать то, что Вы ожидаете здесь перехватить.



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Inga
Дата 7.3.2006, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Ух, вот опять что-то не понятное с этим полем. smile
Если вставляю через буфер, то получаю свой ShowMessage как и предполагалось, но если набираю в это поле то, что нужно (цифры) и нажимаю Enter то поле просто очищается и мое значение пропадает.
Если убрать обработчик, то все нормально. Таким образом, я не могу ввести в поле при наличии этого обработчика любые правильные значения, ничего не происходит в плане ошибок, но после Enter, новая запись очищается.
Как сохранить и обработчик Table1PriseSetText и иметь возможность вводить в это поле нормальные записи?


PM   Вверх
Inga
Дата 7.3.2006, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Вот переделала код:
Код

void __fastcall TForm1::Table1PriseSetText(TField *Sender,
      const AnsiString Text)
{


Currency C;
try {
    C = StrToCurr(Text);
    Table1Prise->Value = C;
    }
    catch(...)
     {
       ShowMessage("Не правильный ввод " + Text);
       Abort();
     }


}

Вроде работает. Это окончательный вариант, или могут быть снова подводные камни и что-то мною не учтено? smile
PM   Вверх
Vyacheslav
Дата 7.3.2006, 13:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Извиняюсь, не заметил, что в Вашем обработчике значение текста никуда не присвавивается.

Тогда уж так
Код

void __fastcall TForm1::ClientDataSet1TestSetText(TField *Sender,
      const AnsiString Text)
{
try {
        Sender->Value = Text;
    }
    catch(...)
     {
       ShowMessage("Не правильный ввод " + Text);
       Abort();
     }



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Inga
Дата 7.3.2006, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Спасибо, но по-прежнему требуется вводить в обработчик все новые и новые проверки. smile
Например, пользователь взял и очистил одну из записей в этой колонке. Теперь он ставит фокус мыши на другую запись и получает ShowMessage("Не правильный ввод " + Text); и курсор остается на месте удаленной записи. Хотелось бы, чтобы после удаления можно было бы перейти на другую запись без проблем.
Следовательно, надо еще и обработать возможность, что пользователь просто очищает запись. Однако пока не знаю как. Курсор остается мигать в месте, где запись удалена и при любом следующем щелчке в стороне на другой записи пользователь получает ShowMessage, пока не введет в удаленную запись цифру.

PM   Вверх
Inga
Дата 7.3.2006, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Очередная моя версия вроде делает то, что надо, но опять же все ли я предусмотрела? Не думала, что простая проверка на ввод значения в поле будет такая замысловатая... smile

Код

void __fastcall TForm1::Table1PriseSetText(TField *Sender,
      const AnsiString Text)
{

try
    {
        Sender->AsString = Text;
        if (Sender->AsString == NULL)
        return;
    }
    catch(...)
     {

       ShowMessage("Не правильное значение " + Text);
       Abort();
     }

}

PM   Вверх
Vyacheslav
Дата 7.3.2006, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Код

void __fastcall TForm1::Table1PriseSetText(TField *Sender,
      const AnsiString Text)
{

   try
        {
            if( Text == "" ) {
                Sender->Clear();
                return;
            }
            Sender->Value = Text;
        }
    catch(...)
     {

       ShowMessage("Не правильное значение " + Text);
       Abort();
     }

}





Цитата

Не думала, что простая проверка на ввод значения в поле будет такая замысловатая...

Это признак того, что у Вас с логикой работы приложения не все впорядке.




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Inga
Дата 7.3.2006, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Спасибо.


>Это признак того, что у Вас с логикой работы приложения не все впорядке.


У меня простое приложение: один дбгрид с данными. Хочется предусмотреть любые не стандартный действия пользователя.
PM   Вверх
Vyacheslav
Дата 7.3.2006, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Начинаем с нуля. Любая даже очень хорошая программа может выдавать ошибки и их надо перехватывать. Цели перехвата могут быть совершенно разные(выдача осмысленного сообщения, журналирование ошибок и пр. пр.). Неужели для этого нужно делать перехват по каждому чиху. Естественно, нет, если по логике перехват по месту не нужен. Следовательно должно быть место цетрализованной обработки ошибок. Решаем это следующим образом
Кладем на форму ApplicationEvents и для начала организуем перехват ошибок вообще и от базы данных в частности
Код

void __fastcall TForm1::ApplicationEvents1Exception(TObject *Sender,
      Exception *E)
{
    if( EDatabaseError* err = dynamic_cast< EDatabaseError*>(E)) {
        ShowMessage("Ошибка работы с БД:" + err->Message );
         return;
    }
    ShowMessage(AnsiString("Программа выполнила недопустимую операцию")+E->Message;
}

Для начала - это все. А весь остальной код убираем. Я не знаю, с какой БД Вы работаете, ну возможно, для нее предусмотрены производные классы от EDatabaseError, которые имеют дополнительную информацию, на основе которой можно выдать более подробные сообщения.
Кроме того, желательно создать свой класс, производный от Exception , который должен нести дополнительную информацию( серьезность ошибки, файл и строка, где произошла ошибка), что бы опять же централизировать обработку ошибоки дать Вам возможность быстро находить бани при работе программы.
Вот например как это выглядит у меня в одном из проектов
Код

void __fastcall TMainDataModule::ApplicationEventsException(
      TObject *a_Sender, Exception *a_Exc)
{
// Если это клиентское исключение, то просто выдаем сообщение...
    try
    {
        if (EipException* Exc = dynamic_cast<EipException*>(a_Exc))
        {
            Exc->Show();
            return;
        }
        // Если это серьезная ошибка
        std::auto_ptr<TErrorDialog> Dlg(new TErrorDialog(this, a_Exc,a_Sender));
        Dlg->ShowModal();
        // если ошибка произошла при входе в систему,
        // прекращаем работу
        if (m_Logining)
            Application->Terminate();
    }
    catch(...)
    {
    }
}





--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Inga
Дата 7.3.2006, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 125
Регистрация: 18.11.2005

Репутация: нет
Всего: нет



Да, круто и красиво. smile
Я работаю с BDE (таблица Paradox). В книжках по БД (те которые у меня), такие красивые решения не описаны. smile
PM   Вверх
Vyacheslav
Дата 9.3.2006, 10:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Кстати пару замечаний по организации работы с БД.
Практика показывает, что редактирование непосредственно в гриде - плохой стиль. Вдвойне плохо, если программа в редактировании входит в автоматическом режиме, только потому, что сделан клик на поле ввода(AutoEdit==true). При работе с БД должен быть четко выделен момент начала редактирования и момент окончания редактирования с возможностью отказа от изменений. А посему грид только для просмотра, а редактирование надо реализовывать в отдельном окне. А в окне с гридом
предусмотреть кнопки редактирования, добавления и возможно просмотра( если в гриде выводится не вся информация.
Тогда обработчики кнопок у Вас будут выглядеть примерно так
Код

 void __fastcall TForm1::EditButtonClick(TObject *Sender)
{
    ClientDataSet1->Edit();
    if(EditDlg->ShowModal() == mrOk){
        ClientDataSet1->Post();
        return;
    }
    ClientDataSet1->Cancel();
}




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.1182 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.