Reflecting property values that should not change back to the UI controls without using Undo

Reflecting property values that should not change back to the UI controls without using Undo

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


Jimbo posted on Wednesday, February 28, 2007

There are many scenarios where (for example) a combo selection is made that is not legal - especially things like "status" values. In the VB6 days we would intercept the index change based on some conditional and immediately restore the "old' value from the object property and pop up a warning message - maybe.

The csla behaviour is strongly biased toward always setting the new selected value and then relying on broken rules to have the user re-select the valid value, or otherwise use undo.
The problem with undo is that it will restore old values for ALL controls at the relevant edit level.

In a property setter, we can prevent the property change based on some business logic; however the control will still show the (unwanted) selected value.

Other than dynamically repopulating the individual (combo) control  to filter the choices based on some state conditions -
 the question really is: how do we refresh the control to restore the old value (which is still the current property value in the BO) without putting business logic in the UI to do it?

jimbo




ajj3085 replied on Wednesday, February 28, 2007

I think you need to stick a BindingSourceRefresh control on your form.  This seems to be a known issue with databinding, and Rocky explains the need for the BindingSourceRefresh control in the chapter on WinForms applications, IIRC.

Jimbo replied on Wednesday, February 28, 2007

As I understand the binding source refresh control purpose, it is only when an property change notification is broadcast that it is applicable. ie all other listeners get the change, but the "current" control is not updated.
This seems to be somewhat different to my case where the PropertyHasChanged call has not even happened.

ajj3085 replied on Wednesday, February 28, 2007

The purpose of the control is to solve the problem you're experiencing, which is the UI assuming whatever value it sticks into the property is the one that will be accepted.

The UI controls assumption is wrong in your case though, because you're not accepting the value; the BindingSourceRefresh forces the control to re-read the property.  I don't think the fact that PropertyHasChanged isn't being called will affect the operation of the component.

Give it a shot; the worse that will happen is that it doesn't solve your problem, and then we can move on from there. Smile [:)]

Jimbo replied on Wednesday, February 28, 2007

thanks .. Will try what you recommend.
BTW is this the same behaviour when you implement CanWriteProperty() authorization on properties and an exception is raised or not?  Currently I can't use csla ApplicationContext to use that level of individual property authorization as we have a different auth architecture.


ajj3085 replied on Wednesday, February 28, 2007

I don't think it is.  Usually if the property setter throws an exception, databinding won't even let you focus off the control.  If it does though, the control may keep the value that was entered, which would be different than the value the BO has... and in that case you'd get similar behavior.. but I'm pretty sure Windows doesn't let focus change if the setting throws an exception.

That said, the 'proper' way to call CanWriteProperty is the overload that DOES thrown an exception.  You prevent the 'cant move focus' problem using the ReadWriteAuthorization control, which will set ReadOnly to true or Enabled to false if CanWriteProperty reports that the property cannot be written to.  Hopefully I've explained that clearly..

Jimbo replied on Wednesday, February 28, 2007

Thankyou ajj  -  the extender control works fine in this scenario.

With respect to throwing custom or system exceptions in property setters. I have found that the exception message will be captured by the ErrorProvider rather than being passed up to the application's exception message handler. The error icon will be shown and the tooltip message (the Exception message) will show once only.
This is happening outside of csla broken rules.

ajj3085 replied on Friday, March 02, 2007

Jimbo,

Glad to hear its working now.

If you don't have the error provider, I don't think windows will let you focus off the control.. which is very frustrating... but its good to know that control will help you figure things out.

Jimbo replied on Friday, March 02, 2007

Andy (ajj)
I am using the ErrorProvider. Also I would mention that there are flags or attributes with IErrorIinfo implementation that provide control over  whether you can move the focus  to allow you to continue or escape the dialog etc.   But I dont see how these are actually applied  in csla.

Perhaps also you can explain why exceptions thrown from property setters are somehow consumed by the ErrorProvider ? and dont get captured in BrokenRules or passed up as unhandled exception messages. ( talking about simple binding here).




RockfordLhotka replied on Friday, March 02, 2007

What attributes are you referring to in regards to IDataErrorInfo?

 

Rocky

 

From: Jimbo [mailto:cslanet@lhotka.net]
Sent: Friday, March 02, 2007 1:15 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Reflecting property values that should not change back to the UI controls without using Undo

 

Andy (ajj)
I am using the ErrorProvider. Also I would mention that there are flags or attributes with IErrorIinfo implementation that provide control over  whether you can move the focus  to allow you to continue or escape the dialog etc.   But I dont see how these are actually applied  in csla.

Perhaps also you can explain why exceptions thrown from property setters are somehow consumed by the ErrorProvider ? and dont get captured in BrokenRules or passed up as unhandled exception messages. ( talking about simple binding here).






Jimbo replied on Friday, March 02, 2007

Rocky,
Sorry I must have implied the wrong info
I think that I was referring to CancelEventArgs settings in the winforms 2 Validating event.
Perhaps there is some conjunction.


 

Jimbo replied on Tuesday, March 20, 2007

A tip for the unwary,
When adding a BindingSourceRefresh control to the component tray from the Toolbox:
The Designer code may automatically associate the control with all of the BindingSources in the following manner eg:

'RootBindingSource
        '
        Me.BindingSourceRefresh1.SetReadValuesOnChange(Me.RootBindingSource, False)

In order for the control to operate as expected for extending simple binding controls, you must check and ensure that the boolean parameter is set to True.

mr_lasseter replied on Wednesday, February 28, 2007

I had a similar issue where I wanted to use AutoComplete, but did not want users to be able to enter new values in the combo box.  I searched the web for a solution, but the only thing I could come up with was subclassing the combo box and  checking if the text of the combo box was in the Items collection in the validating event.

Hope this helps.
Mike

Jimbo replied on Wednesday, February 28, 2007

Mr Lasseter,
That still begs the question that the UI is in charge.  Easy to do but not in the spirit of the MVC framework.



mr_lasseter replied on Wednesday, February 28, 2007

In my scenario, I noticed that if the item is not in the list the value that the control is bound to never gets updated.  So it was not a problem of the UI being in charge it was that the UI never did inform the class that the value had changed. 

It looks like Andy is right the BindingSourceRefresh should fix your problems.  Rocky talks about the same problem you are experiencing popping up in WPF as well.

http://www.lhotka.net/weblog/DataBindingIssueInWPFWithSolution.aspx

RockfordLhotka replied on Wednesday, February 28, 2007

mr_lasseter:

In my scenario, I noticed that if the item is not in the list the value that the control is bound to never gets updated.  So it was not a problem of the UI being in charge it was that the UI never did inform the class that the value had changed. 

It looks like Andy is right the BindingSourceRefresh should fix your problems.  Rocky talks about the same problem you are experiencing popping up in WPF as well.

http://www.lhotka.net/weblog/DataBindingIssueInWPFWithSolution.aspx

The Windows Forms solution to this already exists in CSLA .NET in the form of the BindingSourceRefesh control, which you should use on your Windows Forms forms as discussed in Chapter 9.

The WPF solution isn't totally firmed up yet, but it does turn out that using a value converter automatically solves the problem (though other XAML settings can mess that up). So at the moment I've created a value converter that doesn't actually do any conversion (an identity converter), that you can associate with every editable field. This does resolve the issue, and there's some hope that Microsoft will just plain fix the issue in a future version.

Jimbo replied on Friday, March 02, 2007

ms would have us not using custom objects if the truth be known.

RockfordLhotka replied on Friday, March 02, 2007

That's certainly been true in the past. I think there's a change happening at Microsoft, a move away from the DataSet and toward objects. Unfortunately the move is toward data transfer objects, not "real" objects, so it is important to keep the pressure on Microsoft to continue to evolve toward the right answer (imo anyway Wink [;)]).

Jimbo replied on Friday, March 02, 2007

To get back to the subject of this thread,  the BindingSourceRefresh control works a treat. However because it is a file reference in Csla.Windows, the only way I could get it in the form designer component tray was to hack the form designer code. After that, to apply it in other forms I simply copied it from the first tray and pasted into the other form's tray.  I was impressed that it automatically associated with multiple BindingSources in the one designer, whereas i was expecting to need multiple refresh extenders.
Is there not a way to get the extender control available in the vs Toolbox in the client project - like the ErrorProvider component etc?


mr_lasseter replied on Friday, March 02, 2007

You should be able to add the control by right clicking in the toolbox and chosing chose items.  From there you can browse to the Csla.dll and it will add the control to the Toolbox. 

Mike

Jimbo replied on Friday, March 02, 2007

Thank you Mike,  Simple eh!  I'm far from being a gun IDE practioner (there are so many ways to skin a cat) but I'm also happy that it can be done without the vs wizardry.

ajj3085 replied on Friday, March 02, 2007

That's actually not true.  I was at an MSDN road show yesterday, and it seems moving forward they might ONLY support custom objects..

The presenter said that you cannot use a DataSet or DataTable in Xaml binding because it doesn't implement INotifyPropertyChanged.. the presenter said that may change in the future, but he's not sure if it actually will.

Andy

Copyright (c) Marimer LLC