C# Winforms Errorprovider Control

C# WinForms ErrorProvider Control

This falls in the category of "how can you not know". It is your code that is calling ErrorProvider.SetError(), you should have no trouble keeping track of how many errors are still active. Here's a little helper class, use its SetError() method to update the ErrorProvider. Its Count property returns the number of active errors:

private class ErrorTracker {
private HashSet<Control> mErrors = new HashSet<Control>();
private ErrorProvider mProvider;

public ErrorTracker(ErrorProvider provider) {
mProvider = provider;
}
public void SetError(Control ctl, string text) {
if (string.IsNullOrEmpty(text)) mErrors.Remove(ctl);
else if (!mErrors.Contains(ctl)) mErrors.Add(ctl);
mProvider.SetError(ctl, text);
}
public int Count { get { return mErrors.Count; } }
}

Errorprovider c# winforms

You don't need to make the save button disabled. It's enough to check ValidateChildren method of your form and if it returned false, it means there is some validation error. To use this approach you should remember to set e.Cancel = true in Validating event of the control when you set an error for control.

Also to let the user to move between controls even if there is an error, set AutoValidate property of your Form to EnableAllowFocusChange in designer or using code:

this.AutoValidate = System.Windows.Forms.AutoValidate.EnableAllowFocusChange;

Code for Validation:

private void txtFirstname_Validating(object sender, CancelEventArgs e)
{
if (string.IsNullOrEmpty(this.txtFirstname.Text))
{
this.errorProvider1.SetError(this.txtFirstname, "Some Error");
e.Cancel = true;
}
else
{
this.errorProvider1.SetError(this.txtFirstname, null);
}
}

private void btnSave_Click(object sender, EventArgs e)
{
if (this.ValidateChildren())
{
//Here the form is in a valid state
//Do what you need when the form is valid
}
else
{
//Show error summary
}
}

C# Errorprovider.ContainerControl.Controls contains just TabControl

The TabControl itself is a container which contains TabPages. Those TabPages are containers which contain your textboxes.

The following code will get you want you want but you may want to clean it up to make a recursive call passing in a container so it will work for almost any type.

    private void button1_Click(object sender, EventArgs e)
{
bool ok = true;
foreach (Control c in errorProviderDv.ContainerControl.Controls)
{
if (c is TabControl)
{
foreach (Control t in (c as TabControl).SelectedTab.Controls)
{
MessageBox.Show(t.Name);
if (errorProviderDv.GetError(t) != "")
{
ok = false;
}
}
}
}
}

How can I set an errorProvider against ALL invalid form controls when using this.validateChildren()?

Setting e.Cancel = true is the problem of course. So just don't do that. It is in general a fairly unpleasant feature, making data entry very modal. A much friendlier approach is to give the user free reign of the data entry task, entering data in an order that isn't necessarily the one you envisioned when you set the tab order.

Just write a little helper method that makes it easy. For example:

    private Control firstInvalidControl;

private void SetValidation(object sender, bool ok, string errMsg) {
var ctl = (Control)sender;
if (ok) errorProvider1.SetError(ctl, "");
else {
if (firstInvalidControl == null) firstInvalidControl = ctl;
errorProvider1.SetError(ctl, errMsg);
}
}

Call SetValidation() in the Validating event handlers of your controls. Now you have a very easy time to get all the appropriate warnings displayed, as well help the user navigate to a control that he probably needs to work on first. For example:

    private void OKButton_Click(object sender, EventArgs e) {
firstInvalidControl = null;
this.ValidateChildren();
if (firstInvalidControl != null) firstInvalidControl.Focus();
else {
// Data is good, use it
// ...
}
}

Is it possible to know which control an ErrorProvider is displaying on?

Dispose does not delete an object. The actual deletion is done autmatically by the garbage collector, if there is no variable referencing the object any more.

Dispose is designed to do some clean up prematurely to the actual deletion of an object (e. g. releasing unmanaged memory, closing file descriptors or sockets, ...), see MSDN documentation and tutorial.

To really get the error provider deleted (at a point somewhere in the future), you have to set all references to it to null (or another ErrorProvider).

Either way (by disposing or by setting to null), you won't be able to appropriately use the provider any more afterwards – and if you still need an error provider for future validation, you will have to replace it with a new instance. I can imagine quite well that this not really is what you intended, possibly it is more appropriate for you just to clear the error (using SetError with empty string).

Attention: "The DataSource is a data source that you can attach to a control and that you want to monitor for errors. DataSource can be set to any collection that implements IList." (see MSDN). So you won't get what you expected.

You could instead set the Tag property to the text box and compare ep.Tag == tb (no toString, no name, just directly the reference).

Warning and info provider control in win forms

It is possible to change the icon, if that's your concern. Consider the following, where WarningPNG16x is a PNG image object:

errorProvider1.Icon = Icon.FromHandle(WarningPNG16x.GetHicon());

Of course, if you have an Icon already, just assign it.

As LarsTech pointed out, you could use the SystemIcon versions, as well:

errorProvider1.Icon = SystemIcons.Warning;

Customizing WinForms ErrorProvider to display its icon inside control's entry

I've found a solution:

this.errorProvider.SetIconPadding(this.textBox, -20);

where errorProvider is an ErrorProvider Object and textBox is an Entry object.

how to set errorprovider icon left the control?

Without that code was set.
In the "error Provider" properties, Using the " Right To Left " property.

C# ErrorProvider Want to know if any are Active

Unfortunately, the ErrorProvider control doesn't provide such functionality. You'd best go with the custom error provider classes from the link you posted.

Otherwise, you could create a method that you would call instead of SetError

int errorCount;
void SetError(Control c, string message)
{
if (message == "")
errorCount--;
else
errorCount++;
errorProvider.SetError(c, message);
}

Or you could make an extension method for the ErrorProvider class that would set the error and increment a counter or something along those lines.

And last but not least, you could iterate through all the controls. Slow, but it works:

bool IsValid()
{
foreach (Control c in errorProvider1.ContainerControl.Controls)
if (errorProvider1.GetError(c) != "")
return false;
return true;
}

Edit

I've written a quick extension class for the error provider:

public static class ErrorProviderExtensions
{
private static int count;

public static void SetErrorWithCount(this ErrorProvider ep, Control c, string message)
{
if (message == "")
{
if (ep.GetError(c) != "")
count--;
}
else
count++;

ep.SetError(c, message);
}

public static bool HasErrors(this ErrorProvider ep)
{
return count != 0;
}

public static int GetErrorCount(this ErrorProvider ep)
{
return count;
}
}

I haven't tested it extensively, so you might want to do a bit more validation before calling SetError on your ErrorProvider.



Related Topics



Leave a reply



Submit