WPF bind Textbox to a DataSet in another class -
wpf not area, bit of newbie, , having bit of trouble figuring out how achieve in wpf piece of cake in winforms. can't seem find either right thread in forum or right youtube tutorial leads me towards answer. having problems getting simple databinding wpf textbox working correctly. behaviour trying achieve changes made textbox reflected in source class dataset. it's simple display/edit scenario , i'm sure there simple answer.
this how have done in winforms....
form code:
public partial class form1 : form { private datarecord currentuser; public form1() { initializecomponent(); currentuser = new datarecord(@"data source=c:\users\rr187718\documents\personal\programming\dynamicbackup\dynamicbackup\bin\debug\data\dbdata.sdf"); currentuser.fncbind(ctlcopiestokeep, "value", "tbluser.copiestokeep"); } //test code display value in dataset private void button1_click(object sender, eventargs e) { messagebox.show(currentuser.copiestokeep.tostring()); } }
class code:
public class datarecord { private string connectionstring; private dataset currentrecord; public int copiestokeep { { return int32.parse(currentrecord.tables["tbluser"].rows[0]["copiestokeep"].tostring()); } } public datarecord(string connectionstring) { connectionstring = connectionstring; currentrecord = new dataset(); sql sql = new sql(2); datatable usertable = sql.fncselectastable(connectionstring, "tbluser", "userid=2"); usertable.tablename = "tbluser"; currentrecord.tables.add(usertable); usertable.dispose(); } public void fncbind(control c, string type, string field) { c.databindings.add(type, currentrecord, field, true, datasourceupdatemode.onpropertychanged); } }
i have simple textbox on main form called "ctlcopiestokeep" , "test" button.
does know of nice, simple, example can show how this?
many in advance, dave
edit:
hello noel. many taking time explain that. have put altogether, seems wrong binding, because when change value in textbox not update dataset. here code , xaml. if can point me in right direction appreciated.
updated main code
public partial class mainwindow : window { public datarecord selecteduser; private string connectionstring = @"data source=c:\users\rr187718\documents\personal\programming\dynamicbackup\dynamicbackup\bin\debug\data\dbdata.sdf"; public mainwindow() { initializecomponent(); selecteduser = new datarecord(connectionstring); grdmain.datacontext = selecteduser; } private void button1_click(object sender, routedeventargs e) { selecteduser.fncshowvals("basepath"); } }
updated class code
public class datarecord : inotifypropertychanged { private string connectionstring; private dataset currentrecord = new dataset(); private string basepath = null; public string basepath { { return currentrecord.tables["tblstorage"].rows[0]["basepath"].tostring() ; } set { basepath = value; onpropertychanged("basepath"); } } public event propertychangedeventhandler propertychanged; public datarecord(string connectionstring) { connectionstring = connectionstring; sql sql = new sql(connectionstring, sqlversion.ce); datatable storagetable = sql.fncselectastable(connectionstring, "tblstorage", "userid=2"); storagetable.tablename = "tblstorage"; currentrecord.tables.add(storagetable); storagetable.dispose(); } public void fncshowvals(string test) { messagebox.show(currentrecord.tables["tblstorage"].rows[0][test].tostring()); } protected void onpropertychanged(string value) { propertychangedeventhandler handler = propertychanged; if (handler != null) { handler(this, new propertychangedeventargs(value)); } } }
xaml textbox
<window x:class="wpfbind.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525"> <grid name="grdmain"> <textbox text="{binding basepath, mode=twoway, updatesourcetrigger =propertychanged}" height="23" horizontalalignment="left" margin="124,70,0,0" name="ctlbasefolder" verticalalignment="top" width="120" /> <label content="basefolder" height="28" horizontalalignment="left" margin="41,69,0,0" name="label2" verticalalignment="top" /> <button content="button" height="23" horizontalalignment="left" margin="263,142,0,0" name="button1" verticalalignment="top" width="75" click="button1_click" /> </grid>
update 02/04/2015
i have this, don't understand how references dataset? code produces blank textbox , if value changed doesn't update dataset:
`private string ___basepath = null;
protected string _basepath { { return ___basepath; } set { ___basepath = value; onpropertychanged("basepath"); } } public string basepath { //<- bind property { return ___basepath; } set { _basepath = value; } }`
the underlying dataset value stored here:
currentrecord.tables["tblstorage"].rows[0]["basepath"].tostring();
many in advance, dave.
update - 02/04/2015 - 2
hello noel, have applied code, it's still not working unfortunately (the dataset not reflect changes in textbox if click on "test" button). here whole code. massively appreciate time on way, much!
public partial class mainwindow : window { private string connectionstring = @"data source=c:\users\rr187718\documents\personal\programming\dynamicbackup\dynamicbackup\bin\debug\data\dbdata.sdf"; private readonly datarecord _data = null; public datarecord data { { return _data; } } public mainwindow() { initializecomponent(); _data = new datarecord(connectionstring); datacontext = data; //all controls connected class value in 'data' (datacontext inherits , must property because can bind properties) } private void button1_click(object sender, routedeventargs e) { data.fncshowvals("basepath"); } } public class datarecord : inotifypropertychanged { private string connectionstring; private dataset currentrecord = new dataset(); private string ___basepath = null; private string _basepath { { if (___basepath == null) { //we access currentrecord if did not yet stored value // otherwise read currentrecord every time type char // in textbox. // also: pay attention multiple possible nullreferenceexceptions , indexoutofboundsexceptions ___basepath = currentrecord.tables["tblstorage"].rows[0]["basepath"].tostring(); } return (___basepath == string.empty) ? null : ___basepath; } set { ___basepath = (value == null) ? string.empty : value; notifypropertychanged("basepath"); } } protected void pushbasepathtodatabase() { //save value of ___basepath database } public string basepath { //the binding recieves/sets data from/to property { return _basepath; } set { _basepath = value; } } public event propertychangedeventhandler propertychanged; public datarecord(string connectionstring) { connectionstring = connectionstring; sql sql = new sql(connectionstring, sqlversion.ce); datatable storagetable = sql.fncselectastable(connectionstring, "tblstorage", "userid=2"); storagetable.tablename = "tblstorage"; currentrecord.tables.add(storagetable); storagetable.dispose(); ___basepath = currentrecord.tables["tblstorage"].rows[0]["basepath"].tostring(); } public void fncshowvals(string test) { messagebox.show(currentrecord.tables["tblstorage"].rows[0][test].tostring()); } protected void notifypropertychanged(string propertyname) { if (propertychanged != null) propertychanged(this, new propertychangedeventargs(propertyname)); } }
it great using binding seperate data visuals. since not possible in winforms. in order binding work must following:
the textbox must have datacontext set instance of class holds binding-value.
datacontext = mydatainstance;
can set on textbox or on parent.the value datacontext want bind must public property. f.e:
private string _name = null;
public string name{ get{ return _name; } set{ _name = value; notifypropertychanged("name"); } }
the data class must implement
inotifypropertychanged
if set can write textbox in xaml:
<textblock text="{binding name, mode=twoway, updatesourcetrigger=propertychanged}"/>
this binding binds name property of instance specified in datacontext. can retrieve value property , can write data it.
- it recieves data when call
notifypropertychanged("name");
in dataclass - it writes data when property of control changes (requires
mode
settwoway
,updatesourcetrigger
propertychanged
)
edit (regarding additional content)
noticed wanted notify private field named "basepath"
.
must notify property "basepath"
, not field behind it.
why recommend strict naming convention.
name private , protected fields _privateorprotected
(1 underscore).
name private or protected fields accessed bindings properties ___somedata
(3 underscores) , binding property somedata
. reason is, don't want set private field directly except binding propertie's setter. setting directly not call notifypropertychanged();
isn't want in cases. , if keep 3 underscores throughout app - familliar bindings should understand meaning.
for more complex data might have binding property accessing private/protected property accessing private field. solve this: somedata
, _somedata
, ___somedata
. have make clear wich properties or fields can set in order update binding otherwise might change value of ___somedata
, wonder why binding isn't updating.
since quite important point in every wpf app want understand it. here example stuff above:
private bool ___thisisawesome = true; protected bool _thisisawesome{ get{ return ___thisisawesome; } set{ ___thisisawesome = value; notifypropertychanged("thisisawesome"); } } public bool thisisawesome{ //<- bind property get{ return ___thisisawesome; } /*set{ _thisisawesome = value; } note: setter not accessable outside of class because nobody can tell me not awesome - is. still want able set property correctly within class (in case change mind), why added protected property. if omit getter/setter 1 make sure <br>binding mode</b> not try access omited accessors. check output window find possible binding errors never throw exceptions. */ }
in code should recognize setting thisisawesome
, _thisisawesome
both update binding. beware of setting ___thisisawesome
because won't update binding. setter of thisisawesome
not available (whatever reason) , that's why added protected property. understand want achieve that?
edit2 (because code still doesn't work)
public partial class mainwindow : window { private readonly mydata _data = null; public mydata data{ get{ return _data; } } public mainwindow() { _data = new mydata(); datacontext = data; //all controls connected class value in 'data' (datacontext inherits , must property because can bind properties) } } public class mydata : inotifypropertychanged { private string ___basepath = null; private string _basepath { { if (___basepath == null) { //we access currentrecord if did not yet stored value // otherwise read currentrecord every time type char // in textbox. // also: pay attention multiple possible nullreferenceexceptions , indexoutofboundsexceptions ___basepath = currentrecord.tables["tblstorage"].rows[0]["basepath"].tostring(); } return (___basepath == string.empty) ? null : ___basepath; } set { ___basepath = (value == null) ? string.empty : value; notifypropertychanged("basepath"); } } protected void pushbasepathtodatabase() { //save value of ___basepath database } public string basepath{ //the binding recieves/sets data from/to property get{ return _basepath; } set{ _basepath = value; } } #region inotifypropertychanged public event propertychangedeventhandler propertychanged; protected void notifypropertychanged(string propertyname){ if(propertychanged != null) propertychanged(this, new propertychangedeventargs(propertyname)); } #endregion inotifypropertychanged }
and textbox in mainwindow's xaml:
<textblock text="{binding basepath, mode=twoway, updatesourcetrigger=propertychanged}"/>
Comments
Post a Comment