i've been trying deal frustrating issue regards databinding in winforms.
i have data source, datatable in dataset. datatable has 3 rows. have 3 checkbox controls on form, , button. want bind each checkbox 1 row in data source, , have data source reflect value in checked property whenever checkbox updated. want these changes correctly picked calls haschanges() , calls getchanges().
when button clicked, endcurrentedit() called , passed data-source bound to, , dataset checked changes using haschanges() method.
however, in attempts this, encounter 1 of 2 scenarios after call endcurrentedit().
in first scenario, first checkbox has changes detected. in second scenario, other checkboxes updated value of checkbox last checked on call endcurrentedit().
in looking @ rowstate values after call endcurrentedit(), in scenario 1, first row ever has state of modified. in scenario 2, third row ever has state of modified. scenario 2, doesn't matter whether user updated third checkbox or not.
to demonstrate problem, have created simple example demonstrates it.
it's stock windows form containing 3 checkbox controls , button control, default names.
option strict on option explicit on public class form1 public ds dataset public sub new() ' call required designer. initializecomponent() ' add initialization after initializecomponent() call. ds = new dataset() dim dt new datatable() dt.columns.add("id", gettype(integer)) dt.columns.add("selected", gettype(boolean)) dt.rows.add(1, false) dt.rows.add(2, false) dt.rows.add(3, false) dt.tablename = "table1" ds.tables.add(dt) ds.acceptchanges() integer = 1 3 dim bs new bindingsource() 'after call me.bindingcontext(ds.tables("table1")).endcurrentedit() there 2 scenarios: 'scenario 1 - changes first checkbox detected. 'scenario 2 - when checkbox checked, become checked. 'uncomment first , comment out second see scenario 1. 'uncomment second , comment out first see scenario 2. 'bs.datasource = new dataview(ds.tables("table1")) 'scenario 1 bs.datasource = ds.tables("table1") 'scenario 2 bs.filter = "id=" & dim db new binding("checked", bs, "selected") db.datasourceupdatemode = datasourceupdatemode.onpropertychanged if = 1 checkbox1.databindings.add(db) elseif = 2 checkbox2.databindings.add(db) elseif = 3 checkbox3.databindings.add(db) end if next end sub private sub button1_click( sender object, e eventargs) handles button1.click me.bindingcontext(ds.tables("table1")).endcurrentedit() if ds.haschanges() messagebox.show("number of rows changed: " & ds.getchanges().tables("table1").rows.count) ds.acceptchanges() end if end sub end class i've done lot of searching haven't been able work out what's happening, , @ complete loss. feels i'm trying pretty simple, suspect must have misunderstood somewhere or missed important regards binding process.
edit
it's in second paragraph, make clear, here basic outline of i'm trying do:
- i have
datasetcontainingdatatablevalues. example, there's 2 columns.idinteger, 'selected'booleanvalue. none of these evernothingordbnull. - i want bind each row 1
checkboxcontrol. 1checkboxperidvalue.checkedproperty should boundselectedcolumn indatatable. - when changes made, , user clicks
button, want able tell changes user made, usinghaschanges(),getchanges()methods ofdataset(ie 2 rows updated if user has changedcheckedproperty of 2 ofcheckboxcontrols).
edit 2
thanks @rezaaghaei have come solution. have refined code example of problem, , made controls generate based on data (and position accordingly) make example simple copy-and-paste. also, uses rowfilter on dataview, rather position property of bindingsource.
option strict on option explicit on public class form1 public ds dataset private sub form1_load( sender object, e eventargs) handles mybase.load ds = new dataset() dim dt new datatable() dt.columns.add("id", gettype(integer)) dt.columns.add("selected", gettype(boolean)) dt.rows.add(1, false) dt.rows.add(2, false) dt.rows.add(3, false) dt.tablename = "table1" ds.tables.add(dt) ds.acceptchanges() addhandler dt.columnchanged, sub(sender2 object, e2 datacolumnchangeeventargs) e2.row.endedit() end sub integer = 0 dt.rows.count-1 dim cb new checkbox() {.text = "checkbox" & i+1, .location = new point(10, 25 * (i))} dim dv new dataview(dt) dv.rowfilter = "id=" & directcast(dt.rows(i)(0), integer) dim bs new bindingsource(dv, nothing) dim db new binding("checked", bs, "selected") db.datasourceupdatemode = datasourceupdatemode.onpropertychanged cb.databindings.add(db) me.controls.add(cb) next dim btn new button() btn.location = new point(10, 30 * dt.rows.count) btn.text = "submit" addhandler btn.click, addressof button1_click me.controls.add(btn) end sub private sub button1_click( sender object, e eventargs) 'me.bindingcontext(ds.tables("table1")).endcurrentedit() 'doesn't cut mustard! if ds.haschanges() messagebox.show("number of rows changed: " & ds.getchanges().tables("table1").rows.count) ds.acceptchanges() else messagebox.show("number of rows changed: 0") end if end sub end class the key call endedit() in columnchanged event datatable (a general call endcurrentedit() doesn't appear cut it), although 1 additional problem encountered code won't work if it's in form's new() method, if it's after call initializecomponent(). i'm guessing because there's initialisation winforms after call new() necessary data binding work properly.
i hope example saves others time spent looking this.
consider these corrections , problem solved:
- to bind control specific index of list, bind control binding source containing list, , set position of binding source specifixindex.
- when adding data-binding
checkboxcontrols, set update modeonpropertychanged. - handle
checkedchangedevent ofcheckboxcontrols , callinvalidatemethod of grid show changes in grid. - in
checkedchangedcallendeditofbindingsourcecheckboxbound to. - note: call
endeditusnigbegininvokelet processes of checking checkbox (including updating data source) completed.
c# example
datatable dt = new datatable(); private void form3_load(object sender, eventargs e) { dt.columns.add("id"); dt.columns.add("selected", typeof(bool)); dt.rows.add("1", true); dt.rows.add("2", false); dt.rows.add("3", true); this.datagridview1.datasource = dt; var chekboxes = new checkbox[] { checkbox1, checkbox2, checkbox3 }; (int = 0; < dt.rows.count; i++) { var bs = new bindingsource(dt, null); chekboxes[i].databindings.add("checked", bs, "selected", true, datasourceupdatemode.onpropertychanged); chekboxes[i].checkedchanged += (obj, arg) => { this.datagridview1.invalidate(); var c = (checkbox)obj; var b = (bindingsource)(c.databindings[0].datasource); this.begininvoke(()=>{b.endedit();}); }; bs.position = i; } } vb example
dim dt datatable = new datatable() private sub form1_load(byval sender system.object, byval e system.eventargs) _ handles mybase.load dt.columns.add("id") dt.columns.add("selected", gettype(boolean)) dt.rows.add("1", true) dt.rows.add("2", false) dt.rows.add("3", true) dt.acceptchanges() me.datagridview1.datasource = dt dim chekboxes = new checkbox() {checkbox1, checkbox2, checkbox3} = 0 dt.rows.count - 1 dim bs = new bindingsource(dt, nothing) chekboxes(i).databindings.add("checked", bs, "selected", _ true, datasourceupdatemode.onpropertychanged) addhandler chekboxes(i).checkedchanged, _ sub(obj, arg) me.datagridview1.invalidate() dim c = directcast(obj, checkbox) dim b = directcast(c.databindings(0).datasource, bindingsource) me.begininvoke(sub() b.endedit()) end sub bs.position = next end sub 
Comments
Post a Comment