I'm using infragistics 10.1.20101.1007 with Visual Studio 2010 and VB.Net
I have a winforms app that binds several controls (mostly ultraTextEditor) to a datatable. The text boxes work exactly as I would expect them to, but the ultracheckeditor is not. It shows the data correctly, but the databinding events that keep other bound objects in sync do not happen initially. Only after the first change does the checkbox begin behaving like I would expect. Am I doing something wrong? Is this a bug in the ultracheckboxeditor? Any suggestions?
Thanks,Tony
To duplicate the issue, create the sample app as detailed below (code doesn't paste so well).
Run the app. Note the data in the grid. Modify the text in the text box noting that each keystroke updates the grid.
Run The app. Then modify the checkbox data with a single click. Note that the grid data does not update. Click the checkbox again to modify the value. Now, the grid will stay in sync with the checkbox.
Example App: Need a winforms app with an ultragrid, ultracheckeditor, and ultratexteditor
Example Code:
Public Class Form1Dim _DtData As New DataTableDim _dataLoaded As Boolean = False
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load BuildData() BindData() _dataLoaded = TrueEnd Sub
Private Sub BuildData() Dim col1 As New DataColumn("BitColumn", GetType(Boolean)) Dim col2 As New DataColumn("TextColumn", GetType(String))
_DtData.Columns.Add(col1) _DtData.Columns.Add(col2)
Dim row1 As DataRow = _DtData.NewRow row1.Item("BitColumn") = 1 row1.Item("TextColumn") = "True Value"
Dim row2 As DataRow = _DtData.NewRow row2.Item("BitColumn") = 0 row2.Item("TextColumn") = "False Value"
Dim row3 As DataRow = _DtData.NewRow row3.Item("BitColumn") = 0 row3.Item("TextColumn") = "Another False Value"
_DtData.Rows.Add(row1) _DtData.Rows.Add(row2) _DtData.Rows.Add(row3) _DtData.AcceptChanges()End Sub
Private Sub BindData() Me.UltraGrid1.DataSource = _DtData Dim bndChecked As New Windows.Forms.Binding("CheckedValue", _DtData, "BitColumn") Dim bndText As New Windows.Forms.Binding("Text", _DtData, "TextColumn") bndText.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged bndChecked.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged Me.UltraCheckEditor1.DataBindings.Add(bndChecked) Me.UltraTextEditor1.DataBindings.Add(bndText)End Sub
Private Sub UltraCheckEditor1_CheckedValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles UltraCheckEditor1.CheckedValueChanged If _dataLoaded Then Me.BindingContext(_DtData).EndCurrentEdit()End Sub
Private Sub UltraTextEditor1_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles UltraTextEditor1.ValueChanged If _dataLoaded Then Me.BindingContext(_DtData).EndCurrentEdit()End Sub
End Class
Hi Tony,
It's hard to build a project from a code snippet, because there are too many unknowns, like the version of Visual Studio, the version of the controls, etc.
Can you create a small sample project and attach it here so I can take a look?
To attach a file to your post, just go to the Options tab.
I totally understand, that's why I included that information in the first line of the original post.
I didn't notice the file upload though, or I would have done that instead. Sorry about that.
Here you go. I added a standard check box for comparison.
You will be getting a notice from Infragistics Developer Support in the near future, but I wanted to let you know that we looked into this and it turns out it's not a bug.
Basically, this is an issue of timing. The way binding works in DotNet is actually very simple. There's no magic in the DotNet framework that tells the BindingManager when something changes. What it does is, when you bind to a property (such as CheckedValue) The BindingManager looks for an event on the control called propertynameChanged (e.g. "CheckedValueChanged"). This is the same event your code is hooking into on your sample form. When the control fires the event, the order in which the listeners receive the event is arbitrary. There's no reliable way to tell whether the BindingManager will get the event first or the Form will. It looks like the BindingManager is getting the CheckedChanged event from the CheckBox control first, before the form. So it knows the field is dirty and it updates it as you would expect. In the case of the UltraCheckEditor, it's happening in reverse order. So the CheckValueChanged event handler on the form gets called before the same event has fired for the BindingManager. The BindingManager therefore does not know that anything has changed and so EndCurrentEdit does nothing.
Why it works this way in this particular sample, I can only guess at. Maybe MS deals with their own controls differently. Or maybe it's just a timing issue caused by random chance. It seems to have something to do with the order in which the events are hooked, though.In your sample the order in which events are hooked is arbitrary, since you are using the Handles clause on the event handles. There's no way to know whether the event is hooked at the time you are binding the controls.
Since the idea is to make sure that the form gets the event notificaitons after the BindingManager does, it seems reasonable that if you make sure your application hooks the events after the controls are bound, it will work the way the way you want.Sure enough, if you remove the "Handles" clause from the CheckValueChanged method in the sample and then hook the event at the end of the BindData method, instead, this sample works asyou would expect. This makes sense, since presumably the BindingManager hooks the event when you add the Binding and then your form hooks the event after that. The events therefore fire in that same order. Conversely, if you remove the "Handles" clause from the CheckStateChanged event and instead hook the event at the top of the BindData method, then it displays the same behavior that as the UltraCheckEditor. The first click does not update the grid's display.
My understanding is that it's generally not recommended to rely on the order in which the same event sink fires on multiple objects. So while my test of hooking the event(s) after the binding is added works in this sample, I don't know how reliable it is. So the practical upshot of all of this is that hooking the propertyChanged event and calling EndCurrentEdit it not a reliable way to do things.
I'm not sure what the alternative is, though - expect maybe not to use DataBinding.
Thanks for taking a look at this.
By the way, I may have found a similar issue with the UltraNumericEditor. I'll create another thread if I get a chance to create an example.
Thanks again,Tony
Hello Anthony,
I have logged this as a development issue.
Hi Anthony,
I ran your sample and I see the behavior you are getting. It's very strange. The first time you click the UltraCheckEditor, the CheckedValueChanged event fires. At this point, the DataTable has no changes in it. Then you call EndCurrentEdit and after that, there are still no changes in the DataTable, but the CheckedValue property of the UltraCheckEditor is correctly returning false.
With the inbox CheckBox control, the same thing happens except that the changes do show up in the DataTable after you call EndCurrentEdit. So it looks like the EndCurrentEdit is just not working right the first time. I don't see any obvious reason why that should be.
It does not appear, at first glance, that there is anything wrong the UltraCheckEditor, but it's something we need to look into. So I'm going to forward this thread over to Infragistics Developer Support and have them write this up for developer review.
In the mean time, I noticed that if you bind to the Checked property instead of CheckedValue, it works. So perhaps there is a bug in the BindingManager when dealing with object properties.
Anyway, if you don't need to support DBNull in your boolean field, you could work around the problem by binding to the Checked property. But you will need to be careful and make sure new rows added to the table have a default boolean value for the checkbox and do not default to DBNull, I think.