c# - WPF Binding with Notifyi does not update UI -
my issue ui not updated when propertychanged fired. xaml:
<listbox name="bookshelf" visibility="hidden" selecteditem="{binding selecteditem}" panel.zindex="1" height="auto" grid.column="3" margin="8,50,0,0" horizontalalignment="center" itemssource="{binding bookshelf}" background="transparent" foreground="transparent" borderthickness="0" borderbrush="#00000000"> <listbox.itemtemplate> <datatemplate> <stackpanel verticalalignment="center" orientation="vertical"> <textblock fontsize="14" margin="0,10,0,0" fontweight="bold" foreground="black" horizontalalignment="center" text="{binding path=dbid}" /> <textblock fontsize="16" fontweight="bold" width="170" textwrapping="wrap" foreground="black" margin="5" horizontalalignment="center" text="{binding path=displayname}" /> <image horizontalalignment="center" source="{binding path=bookimage}" width="200" height="200" margin="0,0,0,10" /> </stackpanel> </datatemplate> </listbox.itemtemplate> </listbox>
and:
<combobox margin="8,15,0,0" name="bookshelf_combobox" itemssource="{binding bookshelf}" selecteditem="{binding selecteditem}" verticalalignment="center" horizontalalignment="center" displaymemberpath="displayname" height="22" width="140" visibility="visible" selectionchanged="bookshelf_combobox_selectionchanged"/>
viewmodel:
public class bookshelfviewmodel : inotifypropertychanged { public event propertychangedeventhandler propertychanged; public event showcontentinbrowser showdatabasecontent; public bookshelfviewmodel(showcontentinbrowser showmethod) { showdatabasecontent += showmethod; } private observablecollection<dbinfo> _bookshelf = new observablecollection<dbinfo>(); public observablecollection<dbinfo> bookshelf { { if (_bookshelf == null) _bookshelf = new observablecollection<dbinfo>(); return _bookshelf; } set { if (value != _bookshelf) _bookshelf = value; } } private dbinfo _selecteditem { get; set; } public dbinfo selecteditem { { return _selecteditem; } set { if (_selecteditem != value) { _selecteditem = value; raisepropertychanged(new propertychangedeventargs("selecteditem")); if (_selecteditem == null) return; if (_selecteditem.relatedid != null) showdatabasecontent(_selecteditem, _selecteditem.relatedid); else showdatabasecontent(_selecteditem, _selecteditem.relatedid); } } } public void raisepropertychanged(propertychangedeventargs e) { if (propertychanged != null) propertychanged(this, e); } }
this code i'm using setting datacontext , selecteditem:
await system.windows.application.current.dispatcher.begininvoke( dispatcherpriority.background, new action( () => this.bookshelf.selecteditem = dbinfo ) );
and datacontext:
await system.windows.application.current.dispatcher.begininvoke( dispatcherpriority.background, new action( () => this.bookshelf.datacontext = bookshelfviewmodel ) );
i'm new mvvm design , far have can tell articles have read, cant find what's wrong. i'm guessing using dispatcher not necessary don't think matters in case... listbox show objects updating selecteditem issue here...
update:
heres code dbinfo:
public class dbinfo { public int relatedid { get; set; } public string dbid { get; set; } public tbase3.article currentarticle { get; set; } public string linkid { get; set; } public bool isarticle { get; set; } public string folder { get; set; } public bool isnamedarticle { get; set; } public int currentblockindex { get; set; } public int currentblockcount { get; set; } public string displayname { get; set; } public int vscrollpos { get; set; } public int thtextversion { get; set; } public bool ishtmltoc { get; set; } public imagesource bookimage { get; set; } }
reminder when ever set new value viewmodel -> selecteditem , goes propertychanged(this, e); line. not selected dbinfo selected in listbox.
update2:
i got right side of window list of books, book shelf many books in it. shows book scroll. book selected content being shown in window. if reason want change book code-behind, updates content webbrowser not update listbox book selecteditem
answer: okay found answer right now. code set bookshelf.selecteditem = dbinfo should bookshelfviewmodel.selecteditem = bookshelfviewmodel.bookshelf.first(x => x.dbid == dbinfo.dbif);
await system.windows.application.current.dispatcher.begininvoke(dispatcherpriority.background, new action(() => this.bookshelf.datacontext = bookshelfviewmodel));
that not good, do this? reccomend use of galasoft mvvm light , usage of viewmodellocator, setting datacontext(avaliable through nuget).it provides viewmodelbase, propertychanged needs , works, may extend suit neeeds. sounds datacontext, may actual problem if propertychanged isn't raised.
edit:
as pointed out clemens mode=twoway in binding not needed here, default selecteditem
property anyway, i'll leave example....
<combobox margin="8,15,0,0" name="bookshelf_combobox" itemssource="{binding bookshelf}" selecteditem="{binding selecteditem, mode=twoway}" verticalalignment="center" horizontalalignment="center" displaymemberpath="displayname" height="22" width="140" visibility="visible"> <i:interaction.triggers> <i:eventtrigger eventname="selectionchanged"> <command:eventtocommand command="{binding selecteditemchangedcommand}" passeventargstocommand="true"/> </i:eventtrigger> </i:interaction.triggers> </combobox>
i noticed selectionchanged="bookshelf_combobox_selectionchanged" in code, "nasty", use event command instead, because tying viewmodel views cbox. code above execute command arguments included, add following viewmodel.
public icommand selecteditemchangedcommand{ get; set;} // somewhere in code.. selecteditemchangedcommand = new relaycommand<selecteditemchangedcommand>(onselecteditemchanged); protected void onselecteditemchanged(selecteditemchangedcommand e) { // magic here! or why not call method setter of bound property? }
the wpf cheat sheet nice compact list of types of bindings, handy, used have both @ wall , home, when learning wpf :)
hope helps
cheers
stian
Comments
Post a Comment