ErrorWarnInfoProvider object

ErrorWarnInfoProvider object

Old forum URL: forums.lhotka.net/forums/t/3647.aspx


KKoteles posted on Thursday, October 04, 2007

I've always liked the idea of the ErrorProvider; however, all it displays are the errors.  I couldn't find anything else so I tried my hand at extending it.

If you take a look at the code in my attachment (don't forget to update the references for CSLA before you try to compile!), you can see I've created an ErrorWarnInfoProvider object that that displays all three levels of severity for the BrokenRulesCollection.  I like it a lot, but I can't figure out how to get it to "hook" itself to the appropriate events automatically - so I took a short cut.  Unfortunately that means you need to add the following line (or something like it) within the associated form's constructor:

this.errorWarnInfoProvider1.Initialize(this.Controls);

Obviously there are many areas open for improvement (like being able to set each icon as well as setting it's respective offset from the base ErrorProvider icon, etc); however, I was hoping someone might be able to lead me in the right direction for both trying to tie this into the control events automatically (without needing the Initialize method).

Any suggestions / recommendations?

Thanks,

Ken

ajj3085 replied on Thursday, October 04, 2007

Hmm... well the standard one does this:
System.Windows.Forms.ErrorProvider( this.components )

perhaps that helps?

KKoteles replied on Thursday, October 04, 2007

I realize that the constructor is passed a container object:

        public ErrorWarnInfoProvider(IContainer container)

I’m not exactly sure what that container object is.  I do know it is not the form itself – and I can’t figure out how to “back out” from the component’s within the container (of which my object is one) to get back to the form.  The container object contains components, but it does not contain controls.

I need to be able to get to the Control.ControlCollection of the form in order to set the events correctly.

More ideas?

Ken

ajj3085 replied on Thursday, October 04, 2007

Did you create an extender control?  Because each control that interacts with errorprovider has something like this in the .designer file..

ErrorProvider.Somemethod( Control, true ); // Or false, if the provider should ignore it.

I can't remember what Somemethod is. and its time to go home :-)

KKoteles replied on Thursday, October 04, 2007

Hmmm.  Maybe that is where I took a wrong turn.  I ended up creating a Component Class – because that is what I thought the ErrorProvider object was.  I don’t see extended control as an option (obviously I’m new at creating these); however, there is Inherited User Control.  I didn’t think the ErrorProvider was a control though since technically it doesn’t show up on the form (but rather down in the bottom area).

 

There is very little in my .designer file.  My Component Class just inherits System.Windows.Forms.ErrorProvider, IExtenderProvider

 

Do I need to start from scratch?  Maybe it will look better in the morning...

RockfordLhotka replied on Thursday, October 04, 2007

It does need to be an extender control. Look at Chapter 5, at the ReadWriteAuthorizer and BindingSourceRefresh controls in CSLA itself for some information on creating extender controls.

KKoteles replied on Friday, October 05, 2007

I finally figured out and solved my problem!  Thanks ajj3085 and Rocky for your help.  (It turns out that when I originally started this endeavor I started with a printout of Rocky’s ReadWriteAuthorization.cs; however, I still couldn't quite figure things out at that time.)  

Initially, I was trying to bind my internal Validation_Event to the either the bound control’s KeyUp event (when it’s binding.DataSourceUpdateMode == DataSourceUpdateMode.OnPropertyChanged) or the control’s Validated event (when it’s binding.DataSourceUpdateMode == DataSourceUpdateMode.OnValidation) from within the constructor of my control.  The problem here is that the object’s ContainerControl is null at this point – so there is no way to get any information from the Form that the control has been placed on.  I needed something else to be able to get the information later in the object’s lifecycle.

The only thing I knew that needed to be set was the DataSource property; however, since I was inheriting from the ErrorProvider that property already existed.  The solution was to force my object to get the DataSource property – and then pass that value to the base object.  The “trick” here was to add the keyword “new” to the property in order to hide the base object’s property.  Just when I thought I had it figured out, I ran into another problem.  At the time the DataSource property value is set, the object’s ContainerControl is populated; however, its Controls collection is still empty.  OK, somehow I need to delay even further.  The way I was able to do this was to create an EventHandler and tie it to the object’s ContainerControl.BindingContextChanged event.  It just happens that by the time the BindingContextChanged event is fired – the ContainerControl.Controls collection is populated.  At this point, I am home free and I just need to bind to each control’s KeyUp or Validated event like I did before.

The attached control should be “safe” for all BindingSources; however, the warning and information features will only function if the bound object is a Csla.Core.BusinessBase object – because those are the only ones I know how to extract.  I’ve included the updated files as an attachment.  Again, don’t forget to set your reference to your Csla.DLL.  I hope someone finds this useful!

Enjoy,

Ken

KKoteles replied on Monday, October 29, 2007

I've attached the latest version.  I had a request so I thought I'd update it.  There are two things I improved.  Initially it did not take into account controls within controls (like textboxes, etc within tabs).  Additionally, when I cancelled an edit on an object it was not clearing the warnings and information items.  I fixed that.

 

Enjoy,

Ken

RockfordLhotka replied on Monday, October 29, 2007

Are you willing to put this into CSLAcontrib? That may make it more discoverable for people who want to use it?

 

Rocky

 

From: KKoteles [mailto:cslanet@lhotka.net]
Sent: Monday, October 29, 2007 4:19 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] ErrorWarnInfoProvider object

 

I've attached the latest version.  I had a request so I thought I'd update it.  There are two things I improved.  Initially it did not take into account controls within controls (like textboxes, etc within tabs).  Additionally, when I cancelled an edit on an object it was not clearing the warnings and information items.  I fixed that.

 

Enjoy,

Ken



KKoteles replied on Monday, October 29, 2007

Rocky,

 

That would be great.  I haven’t spent too much time on the CSLAcontrib portion of the web site.  If that is the best place, then great.  If you would even want to add it along with ReadWriteAuthorization, that would be great too!

 

Is there anything I need to do in order to put it into CSLAcontrib?

 

Thanks,

Ken Koteles (K2)

RockfordLhotka replied on Wednesday, October 31, 2007

Ideally you’d put it into CSLAcontrib yourself, especially if you have any plans to alter it or update it going forward.

 

If you don’t want to do that, I can add it to the repository for you, but that won’t allow you to do any updates over time.

 

If you want to use the repository directly, just create an account on www.codeplex.com and email me your user id. I’ll make you a contributor on the site so you have read/write access to the repository.

 

The site uses TFS behind the scenes, so to get code in/out you need to have a TFS client installed. Microsoft has a free one you can download, that integrates with VS 2005 (and soon 2008). I believe there’s also a client on codeplex that integrates with the Windows shell much like TortoiseSVN – but I haven’t had time to go find that yet.

 

Rocky

 

 

From: Kenneth Koteles [mailto:cslanet@lhotka.net]
Sent: Monday, October 29, 2007 7:55 PM
To: rocky@lhotka.net
Subject: RE: [CSLA .NET] ErrorWarnInfoProvider object

 

Rocky,

 

That would be great.  I haven’t spent too much time on the CSLAcontrib portion of the web site.  If that is the best place, then great.  If you would even want to add it along with ReadWriteAuthorization, that would be great too!

 

Is there anything I need to do in order to put it into CSLAcontrib?

 

Thanks,

Ken Koteles (K2)
(904) 220-0118

 

From: Rockford Lhotka [mailto:cslanet@lhotka.net]
Sent: Monday, October 29, 2007 7:43 PM
To: KKoteles@comcast.net
Subject: RE: [CSLA .NET] ErrorWarnInfoProvider object

 

Are you willing to put this into CSLAcontrib? That may make it more discoverable for people who want to use it?

 

Rocky

 

From: KKoteles [mailto:cslanet@lhotka.net]
Sent: Monday, October 29, 2007 4:19 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] ErrorWarnInfoProvider object

 

I've attached the latest version.  I had a request so I thought I'd update it.  There are two things I improved.  Initially it did not take into account controls within controls (like textboxes, etc within tabs).  Additionally, when I cancelled an edit on an object it was not clearing the warnings and information items.  I fixed that.

 

Enjoy,

Ken

 

 



Tbot155 replied on Thursday, November 15, 2007

Thanks for posting this control. I've been looking for something like this.

I do have one question though. When changing one property causes another property to be valid, the 'information' and 'warning' icons on the newly valid property are not cleared. When I run the same test with the severity set to 'error' it works fine, but when it's set to 'information' or 'warning' I need to physically cause validation (by tabbing out of a textbox, etc) to cause the icon to dissappear.

Am I doing something wrong?

Thanks

KKoteles replied on Friday, November 16, 2007

Tbot155,

No - you are not doing anything wrong.

The reason the 'error' icon is working correctly is because underneath my control is an actual ErrorProvider - and it is working like it always had.  The 'problem' is that for the other two icons I am hooking to change events off the bound control.  In your case, with dependant properties - control2 is changing and the validation / business rule violations are cleared for control1 as a result.  My problem is that control1 didn't change; therefore, I don't have anyway (right now anyway) to notify my control that control1 needs to have its icons updated.

Looks like I have more work to do...  I've been a little tied up. Hopefully I will get this control into CSLAContrib shortly.  After that, I'll try to spend some time to see if I can't figure out a way to keep my control 'aware' of the changes to the business object itself and not just the controls bound to it... 

Thinking out loud...  Seems like I'll need to keep an internal array of all the bound controls - and when any one of them changes, then check / reverify all the others as well.  Have to make sure this isn't a hit on performance too.  Maybe there is a way to store a count of broken rules for each bound control - then only address the 'non-triggering' controls if their broken rule count changes.  Hmmm - need to make sure I address newly broken rules and not just cleared rules.

I've got some ideas.  I'll see what I can come up with.  Thank you for the feedback!!!

Ken

Tbot155 replied on Friday, November 16, 2007

Thanks Ken. Great work so far. Looking forward to seeing what you come up with.

KKoteles replied on Monday, November 26, 2007

All,

Latest code (including the change Tbot155 requested) is now on CSLAContrib.

Enjoy,

Ken

akhirudin replied on Sunday, May 04, 2008

Hallo all, I've download the latest files of this control from CSLAContrib, but I can't make it works to show the warning nor Information icons, but it works ok to shows the Error Icon

am I missing something?

Thank you

 

ajj3085 replied on Friday, October 05, 2007

That's fine; you just need to implement IExtenderProvider.  Rocky's code should prove as a good example, he has the ReadWriteAuthorization component.

JonnyBee replied on Wednesday, May 07, 2008

Hi all,

I have done a bit of change to the ErrorWarnInfoProvider.
1. Only hooks to the DataBindingSource - not to change event on UI controls
2. A new property for "ShowMostSevereOnly" to only display most severe icon and message
3. Works properly on initalization of bindingsource.
4. Processes all UI controls bound to BindingSource when properties or current is changed.
5. Set default blink rate to 0 (I find blinking is annoying to users)
6. Optimized performance on processing properties.

Hope this works fine for your projects too.

/jonny


akhirudin replied on Wednesday, May 07, 2008

Hallo Jonny

Thank you for your reply, really appriciate this

anyway I've download your files and put it to the latest project I've download from contrib site, but it's still not working for Warning or Information validation, can you please send me the complete project file.

btw, I am using this on VB.Net project which is using CSLA 2.1.4 version

Thank you

Fahmi

Harry_Seldon replied on Wednesday, May 07, 2008

Hi Fahmi,

I've got the same problem. I'm using CSLA 3.0.3. Errors show up but Warnings and Info do not.

Not really clear to me how I'm supposed to use this nearly really really useful control. I included the code in the Csla project in the Windows folder/namespace, then I referenced Csla as usual. Added the control to my VS Toolbox, dragged it onto my form creating errorWarnInfoProvider1.

If I do nothing more, errors will display as usual. Warning and Information severity broken rules do not.

I tried setting the errorWarnInfoProvider1.Datasource to the same as my dataGridView1 control, had no effect.

Anybody wana sell us a vowel?

-Harry

JonnyBee replied on Wednesday, May 07, 2008

Hi All,

I have added a sample Form1 and a TestBusinessObject to the project and tested with Csla 2.1.4 (and we are using 3.0.4 at our regular projects). Hope this helps to show the usage of the ErrorWarnInfoProvider.

/jonnybee

JonnyBee replied on Wednesday, May 07, 2008

Please note - this provider does not work with DataGridView (nor does the standard ErrorProvider). The DataGridView has its own internal implementation of the ErrorProvider (and how error icons are shown - properties like ShowCellErrors and ShowRowErrors).

The ErrorWarnInfoProvider works with most other standard windows controls - as the ordinary ErrorProvider does (and it is actually ErrorProviders doing the work).

/jonnybee

Harry_Seldon replied on Wednesday, May 07, 2008

<quote>
Please note - this provider does not work with DataGridView
</quote>

whoops = that would be the one little thing I was missing.!!!

Appreciate your help johnnybee!
Wow, I'm going to have to put my thinking hat on now :-( 

akhirudin replied on Wednesday, May 07, 2008

Hallo Jonny

 

thank you foy your assistance, I've download your sample and it works great

I'll now try to implement on my project.

 

Really appriciate this mate

Harry:

CSLAerror Treeview looks good enought to provide Grid (Collection) validation with severity

however it would be great if we can have the validation provider attach to the grid

 

cheers

 

 

 

akhirudin replied on Thursday, May 08, 2008

Hallo Jonny

 

I'ts working good

 

Thank you so much

Annesh replied on Friday, May 23, 2008

Hi all

I am using VS2008 Teams edition, the sample runs fine, but when i open the form1 in the designer i recieve the following error: "Type 'ErrorWarnInfo.ErrorWarnInfoProvider' does not have a constructor with parameters of types DesignerHost.". If i create a new windows form and try to drag this control within it, i also recieve this error and it does not allow me to add this control to a new form. Please advise.

Thanks in advance

akhirudin replied on Sunday, May 25, 2008

Hi

I haven't got chance to to try this on VS2008

but you may please try directly add compiled library in my attachment into your CSLA UI project

or if you want to add the project directly into your solution I think you need to convert the project first.

FYI the attachments referenced into CSLA.Net Version 2.1.4

i'm not sure it will work if you are using the newer version CMIIW

 

Regards

Fahmi

 

stefan replied on Monday, July 28, 2008

I am still having this same issue with VS2008.

Did someone find a solution to this designer problem?

Stefan

tiago replied on Monday, November 24, 2008

Hi JonnyBee,

I download and tested both files bellow
ErrorWarnInfoProvider2.zip (2008  May 07, 09:06)
ErrorWarnInfoProvider2_withsample.zip (2008  May 07, 20:06)

The later has an extra line on ErrorWarnInfoProvider.cs:
public bool ShowOnlyMostSevere, line 460
ProcessAllControls();

I guess this is the correct one. Can you confirm?

reagan123 replied on Wednesday, July 30, 2008

***EDIT***
Nevermind... must have had old version.  Issue with icon resolved by downloading new version.

Thanks for the awesome tool!

Michael replied on Thursday, June 02, 2011

Hi Ken and others

Thanks for all the hard work so far. I know I'm pretty late to the party, but I've attached a new version which uses reflection to subscribe to the standard ErrorProvider's ErrorManager_BindingsChanged, ErrorManager_ItemChanged and ErrorManager_CurrentChanged events. This means that we don't have to rely on the controls' KeyUp or Validated events to trigger our updates (which was problematic), and there's also no need for a costly ProcessDependentProperties loop. As soon as you bind your CSLA object to the binding source, if there are errors, warnings or information to display, they show up.

As a personal preference, I've converted it to a non-partial class with no designer file, and moved the icons into a resource file, so they can be reused more easily. Ken's information and warning icons are included in the zip which will need to be added to a resource file to get the class to build.

Kind regards

Michael

Alan Hinton replied on Friday, June 17, 2011

Michael

Thanks, your code does just what I was looking for.

I have added your code to my project and it works fine for warnings, but the info items don't show up.  I have the ShowInformation bool set to true, but it doesn't seem that these bools do anything anyway.

Alan

JonnyBee replied on Sunday, June 19, 2011

Hi Alan,

There is also a version on http://cslacontrib.codeplex.com that you could look at.

I've updated the code and used this in several projects and works fine with all error levels.

 

Michael replied on Sunday, June 19, 2011

Hi Alan

Sorry for the late reply.

I've just tested it again, and it's working fine for me. I get error, warning and information icons showing (concurrently when appropriate). I'm using the default settings for the ErrorWarningInformationProvider component and CSLA 3.8.3.Try updating the following sample validation methods and add them to one of your business objects:

            ValidationRules.AddRule<Project>(TestError      <Project>, NumberProperty);
            ValidationRules.AddRule<Project>(TestWarning    <Project>, NumberProperty);
            ValidationRules.AddRule<Project>(TestInformation<Project>, NumberProperty);
        }
 
        private static bool TestError<T>(T target, RuleArgs e) where T : Project
        {
            e.Description = "An error.";
 
            return false;
        }
 
        private static bool TestWarning<T>(T target, RuleArgs e) where T : Project
        {
            e.Description = "A warning.";
            e.Severity    = RuleSeverity.Warning;
 
            return false;
        }
 
        private static bool TestInformation<T>(T target, RuleArgs e) where T : Project
        {
            e.Description = "Some information.";
            e.Severity    = RuleSeverity.Information;
 
            return false;
        }

For the reasons mentioned earlier, this new version of the error provider is much better, so it's well worth getting it to work.

Kind regards

Michael

Alan Hinton replied on Monday, June 20, 2011

Michael

Thanks for looking into this.  After much head scratching I found the problem: I have multiple bindings for each control, for things like 'enabled' as well as 'value'.  The code in your zip applied only the warning or info items from the 'last' binding for any given control.  The 'last' binding is effectively random, which is why I was seeing some icons and not others, it just happened that I wasn't seeing info items.

I have updated the code, attached, to deal with multiple bindings on each control and join together all the warning and info items for all the bindings.  During working with the code I ended up converting chunks of it to our house coding style and made a few other minor changes, hope this doesn't grate too much.  I also modified it to have the icons shuffle up so that warnings are only offset if there are no errors and so on.

Cheers

Alan

 

Michael replied on Monday, June 20, 2011

Ah, multiple bindings, I hadn't tested that. Excellent, thanks for the update, I'll check it out.

Kind regards

Michael

Michael replied on Monday, June 20, 2011

Hi Alan

That would have given me a nasty surprise when my information and/or warnings weren't showing up. Because we haven't had a way to display warnings and information effectively until recently, we haven't really made use of them yet. (Fixing the error / warning / information provider is something that's been on my to-do list for about two years now.)

I had only done a simple test harness on a text box with only the Text bound, which of course worked with the code as it was. Naturally, we have heaps of controls with multiple bindings, so this definitely would have been a pain.

Thanks for fixing this; it works great. Your icon offset is a much better implementation, too.

Kind regards

Michael

JonnyBee replied on Tuesday, August 02, 2011

Hi all,

I believe you may have a very eager updating in your ErrorWarningInformationProvider.

I added the control to the BussinessRuleDemo sample (just a simple editing form) and

on startup (update all fields called 20 times):

ErrorWarninInformationProvider: ErrorManager_ItemChanged
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890831453995
ErrorWarninInformationProvider: ErrorManager_ItemChanged
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890831493997
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832144035
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832164036
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832174036
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832174036
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832184037
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832194037
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832194037
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832254041
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832264041
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832264041
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832274042
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832274042
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832284043
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832284043
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832294043
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478890832294043

Per each editing of a field (called 2 times):

ErrorWarninInformationProvider: ErrorManager_ItemChanged
ErrorWarninInformationProvider: ErrorManager_CurrentChanged: 634478891076398005

I do believe you should consider to attach to the CurrentItemChanged event on the BindingSource.

Michael replied on Tuesday, August 02, 2011

It's subscribing to the base ErrorProvider's ItemChanged and Bindings.CollectionChanged events. As far as I know, this is what's required to make the errors, warnings and information respond immediately OnPropertyChanged. Because it's subscribing to the base error provider events, it cannot be very much less efficient than the standard one.

JonnyBee replied on Wednesday, August 03, 2011

Same sample with my ErrorWarnInfoProvider from CslaContrib will:

on startup (called 3 times)

ErrorWarnInfo: CurrentItemChanged, 634479584377318706
ErrorWarnInfo: CurrentItemChanged, 634479584377358708
ErrorWarnInfo: CurrentItemChanged, 634479584377398710

on a property changed (1 time):

ErrorWarnInfo: CurrentItemChanged, 634479584450912915

http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.currentitemchanged.aspx

"The CurrentItemChanged event is raised in response to all of the circumstances that raise the CurrentChanged event. Additionally, CurrentItemChanged is also fired whenever the value of one of the properties of Current is changed."

JonnyBee replied on Wednesday, August 03, 2011

I think my issue is with:

                    currencyManager.Bindings.CollectionChanged += ErrorManager_BindingsChanged;

causing the update to be called as each databinding is added to the CurrencyManager.Bindings collection.

The number of fields (controls) that is databound to the BindingSource  - is the same amount of times the update will be called on startup + when other events is called!!

You should probably hook into

events - which is essentially the same as BindingSource.CurrentItemChanged event.

CurrencyManager.CurrentItemChanged

http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingmanagerbase.currentitemchanged.aspx:

"The CurrentItemChanged event occurs whenever there is a change in the state in the currently bound item. This can occur if one of the properties of this item is changed or if the item itself is replaced or moved."

Copyright (c) Marimer LLC