c# - How to make TwoWay Binding work -
i have problem when put binding mode
twoway
datagrid
won't show. when leave binding mode
on default, datagrid
apear strings
, , cannot find problem. in xaml
have 3 more button
s: load
(that loads table), update
, cancel
(that cancel changes , reloads datagrid
directly observablecollection
.
here xaml
datagrid
line
<datagrid x:name="datagrid" autogeneratecolumns="true" canvas.left="10" canvas.top="10" alternatingrowbackground="lightgreen" height="245" width="500" itemssource="{binding userss.getvalues, mode=twoway, updatesourcetrigger=propertychanged}" datacontext="{binding relativesource={relativesource self}}"/>
i have userss
class
creat observablecollection
store data sqlite
database
.
public class userss : inotifypropertychanged { public static sqliteconnection m_dd = new sqliteconnection("data source=mydatabase.sqlite;version=3;"); public static observablecollection<userss> usercol = new observablecollection<userss>(); public int id { get; set; } private string _name; public string name { { return _name; } set { _name = value; raisepropertychanged(); } } private sex _sex; public sex sex { { return _sex; } set { _sex = value; raisepropertychanged(); } } private stations _station; public stations station { { return _station; } set { _station = value; raisepropertychanged(); } } private jobs _job; public jobs job { { return _job; } set { _job = value; raisepropertychanged(); } } private datetime _date; public datetime date { { return _date; } set { _date = value; raisepropertychanged(); } } public static observablecollection<userss> getvalues() { m_dd.open(); string sql = "select * user"; usercol.clear(); sqlitecommand cmd = new sqlitecommand(sql, m_dd); sqlitedatareader reader = cmd.executereader(); while (reader.read()) { string sex1 = reader["sex"].tostring(); string station1 = reader["station"].tostring(); string job1 = reader["job"].tostring(); string data1 = reader["date"].tostring(); usercol.add(new userss() { id = convert.toint32(reader["id"]), name = reader["name"].tostring(), sex = (sex)enum.parse(typeof(sex), sex1), station = (stations)enum.parse(typeof(stations), station1), job = (jobs)enum.parse(typeof(jobs), job1), date = convert.todatetime(data1) }); } m_dd.close(); return usercol; } public event propertychangedeventhandler propertychanged; private void raisepropertychanged([callermembername] string caller = "") { if (propertychanged != null) { propertychanged(this, new propertychangedeventargs(caller)); } } } public enum sex { male, female } public enum jobs { programmer, designer, manager, cto, ceo, } public enum stations { desktop, laptop, tablet }
}
and here implementation mainwindow
public partial class mainwindow : window { public sqliteconnection m_db = new sqliteconnection("data source=mydatabase.sqlite;version=3;"); sqlitedataadapter adap; dataset ds; datatable dt; sqlitecommandbuilder cmdbl; string query; public mainwindow() { initializecomponent(); } private void loadbutton_click(object sender, routedeventargs e) { try { m_db.open(); observablecollection<userss> cuser = userss.getvalues(); query = "select * user"; adap = new sqlitedataadapter(query, m_db); ds = new dataset(); adap.fill(ds, "users"); dt = ds.tables[0]; datagrid.datacontext = ds.tables[0].defaultview; datagrid.itemssource = dt.defaultview; m_db.close(); } catch (exception ex) { messagebox.show(ex.tostring()); } } private void update_click(object sender, routedeventargs e) { if (messagebox.show("are sure want make changes?", "please confirm", messageboxbutton.yesno) == messageboxresult.yes) { try { cmdbl = new sqlitecommandbuilder(adap); adap.update(ds, "users"); ds.tables[0].acceptchanges(); datagrid.items.refresh(); } catch (exception ex) { messagebox.show(ex.message); } } else this.datagrid.canceledit(); } private void cancelclick(object sender, routedeventargs e) { if (messagebox.show("are sure want cancel changes?", "please confirm", messageboxbutton.yesno) == messageboxresult.yes) { datagrid.itemssource = userss.getvalues(); } else this.datagrid.canceledit(); } }
}
btw work in wpf
.
hope can me. thanks.
the problem binding function, doesn't work. should bind public property contains list of models want show in datagrid. way need move getvalues
call somewhere else, allready have code in loadbutton_click
event-handler, reuse that.
so first change change usercol
-collection public property instead of public field, because bindings work on public properties, besides want raise propertychangedevent
if reference observablecollection
changes.
// old code public static observablecollection<userss> usercol = new observablecollection<userss>(); // new code private static observablecollection<userss> usercol = new observablecollection<userss>(); public static observablecollection<userss> usercol { { return usercol; } set { usercol = value; raisepropertychanged(); } }
your getvalues
-method doesn't need return type anymore, change void. inside, change every call usercol
new public property usercol
if changes list happen, gui needs (via raisepropertychanged
e.g.)
inside of loadbutton_click
doing same in getvalues
function doesn't make sense, because don't use userss
models anymore. can instead use getvalues
-method here reload data (also need event e.g. datagridloaded or fill data @ startup):
private void loadbutton_click(object sender, routedeventargs e) { // ... exception handling userss.getvalues(); }
now bind collection in xaml view:
<datagrid x:name="datagrid" autogeneratecolumns="true" canvas.left="10" canvas.top="10" alternatingrowbackground="lightgreen" height="245" width="500" itemssource="{binding userss.usercol, mode=twoway, updatesourcetrigger=propertychanged}" datacontext="{binding relativesource={relativesource self}}"/>
note general idea , have not testet code, maybe need fix in view places. think if bit mvvm design pattern structure code in nice fashion.
Comments
Post a Comment