Здесь. Это должно сэкономить вам тонну работы.
Вкратце: для проверки привязанного элемента управления есть три события, которые вы хотите обработать.
- Событие
Control.Validating
, которое проверяет данные, когда пользователь покидает элемент управления,
- Событие
Control.Validated
, которое обновляет источник данных, если и только если он правильно проверен, и
- Событие
Binding.Parse
, которое проверяет данные, когда что-либо еще изменяет данные в элементе управления (т. Е. Ваш код).
Чтобы гарантировать, что в источник данных записываются только действительные данные, автоматическое обновление связанных данных отключается при создании Binding
- таким образом, данные only записываются в источник данных во время события Control.Validated
.
И события Validating
, и Parse
помещают сообщение об ошибке проверки в ErrorProvider
, присоединенный к границе Control
; у вас может быть другой способ представления сообщений об ошибках, и в этом случае вам нужно будет изменить оба этих события.
Вы также можете обработать событие привязки Format
, чтобы управлять представлением данных в поле в связанном элементе управления.
Я не переписывал этот код, чтобы сделать его универсальным, потому что я не хочу вносить никаких ошибок. Поэтому я объясню, что такое fc
и cm
, насколько вам нужно знать, чтобы заставить это работать.
fc
- это экземпляр класса, который оборачивает связанные с моим приложением объекты Control
. Он имеет свойство Control
(очевидно, обернутый элемент управления), а затем свойства Binding
и ErrorProvider
, использование которых показано ниже. Обратите внимание, что, поскольку этот код устанавливает привязку данных для вас, вы не настраиваете привязку элемента управления в конструкторе форм. Вам, строго говоря, не нужен этот класс для того, чтобы этот код работал, но он несколько упрощает код. (Весь код здесь взят из статического метода класса fc
, которому был передан BindingSource
, как показано.)
cm
- это экземпляр класса, который содержит метаинформацию о столбце данных, к которому я привязываю элемент управления, а именно:
ColumnName
, его имя в источнике данных (я, очевидно, привязываюсь к DataColumn
),
PropertyName
, имя свойства элемента управления, с которым оно связано (например, "Text"
),
NullValue
, как описано в документации для Binding.NullValue
,
Format
, метод, который форматирует внутреннее значение столбца для отображения в связанном элементе управления, и
Parse
, метод анализа ввода во внутреннее значение столбца. Фактическая логика проверки для столбца живет здесь.
Очевидно, что это C #, поэтому вам нужно возиться с ним, чтобы заставить его работать в VB, но различия должны просто зависеть от синтаксиса.
// add an ErrorProvider to the control so that we have a place to display
// error messages
fc.ErrorProvider = new ErrorProvider {BlinkStyle = ErrorBlinkStyle.NeverBlink};
// create the Binding. DataSourceUpdateMode.Never bypasses automatic updating
// of the data source; data only gets written to the data source when the
// column is successfully validated.
fc.Binding = fc.Control.DataBindings.Add(
cm.PropertyName,
bindingSource,
cm.ColumnName,
true,
DataSourceUpdateMode.Never,
cm.NullValue);
// this is called whenever the Binding pushes data back to the data source;
// it parses the data in the control into an object that's returned in e.Value.
fc.Binding.Parse += delegate(object sender, ConvertEventArgs e)
{
string property = fc.Binding.PropertyName;
object unparsedValue = fc.Control.GetType().GetProperty(property).GetValue(fc.Control, null);
string message;
// note that we don't actually care about the parsed value if message
// is not null (i.e. if the value is invalid). by convention it's null,
// but it won't ever get written back to the data source.
object parsedValue = cm.Parse(unparsedValue, out message);
if (message != null)
{
fc.ErrorProvider.SetError(fc.Control, message);
}
else
{
fc.ErrorProvider.Clear();
}
e.Value = parsedValue ?? DBNull.Value;
};
// this is called whenever the user leaves the Control.
fc.Control.Validating += delegate
{
string property = fc.Binding.PropertyName;
object value = fc.Control.GetType().GetProperty(property).GetValue(fc.Control, null);
string message;
cm.Parse(value, out message);
if (message != null)
{
fc.ErrorProvider.SetError(fc.Control, message);
}
else
{
fc.ErrorProvider.Clear();
}
};
// this, combined with the DataSourceUpdateMode of Never, insures that the Control's
// value only gets pushed out to the data source after validation is successful.
fc.Control.Validated += delegate {
fc.Binding.WriteValue();
};
// this is called whenever the Binding pulls data from the data source into
// the bound Control
fc.Binding.Format += delegate(object sender, ConvertEventArgs e)
{
e.Value = cm.Format(e.Value);
};