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
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
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...
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.
Enjoy,
Ken
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
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
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)
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
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
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
Thanks Ken. Great work so far. Looking forward to seeing what you come up with.
All,
Latest code (including the change Tbot155 requested) is now on CSLAContrib.
Enjoy,
Ken
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
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
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
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
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
Hallo Jonny
I'ts working good
Thank you so much
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
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
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?
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
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
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.
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
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
Ah, multiple bindings, I hadn't tested that. Excellent, thanks for the update, I'll check it out.
Kind regards
Michael
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
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.
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.
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."
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
"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