c# - Update ObservableCollection from BackgroundWorker/ProgressChanged Event -
i'm writing simple tool troubleshooting computers. wpf window listbox
bound observablecollection<computerentry>
computerentry
simple class containing computer host name, , status. tool ping each compute name in list, , if response received computerentry.status
updated indicate computer connected network somewhere...
pinging can take time, couple seconds per computer depending on if has timeout or not. i'm running actual ping in backgroundworker
, using reportprogress
method update ui.
unfortunately observablecollection
not seem raise propertychanged
event after objects updated. collection update new information, status never changes in listbox
. presumably because not know collection has changed.
[edit] per fantasticfix, key here is: "the observablecollection fires when list gets changed (added, exchanged, removed)." since setting properties of object instead of modifying it, observablecollection not notifying list of change -- didn't know how. after implenting inotifypropertychanged
works fine. conversly, replacing object in list new updated instance fix problem. [/edit]
btw i'm using c# 3.5 , i'm not in position can add additional dependancies tpl.
so simplified example [that won't compile without more work...]:
//real 1 more hey example... public class computerentry { public string computername { get; private set; } public string status { get; set; } public computerentr(string computername) { this.comptuername = computername; } } //...*in window code*... private observablecollection<computerentry> computerlist { get; set; } private backgroundworker refreshworker; private void init() { refreshworker = new backgroundworker(); refreshworker.workerreportsprogress = true; refreshworker.dowork += new doworkeventhandler(refreshworker_dowork); refreshworker.progresschanged += new progresschangedeventhandler(refreshworker_progresschanged); } private void refresh() { refreshworker.runworkerasync(this.computerlist); } private void refreshworker_dowork(object sender, doworkeventargs e) { list<computerentry> complist = e list<computerentry>; foreach(computerentry o in complist) { computerentry updatedvalue = new computerentry(); updatedvalue.status = indicatorhelpers.pingtarget(o.computername); (sender backgroundworker).reportprogress(0, value); } } private void refreshworker_progresschanged(object sender, progresschangedeventargs e) { computerentry updatedvalue = new computerentry(); if(e.userstate != null) { updatedvalue = (computerentry)e.userstate; foreach(computerentry o in this.computerlist) { if (o.computername == updatedvalue.computername) { o.status = updatedvalue.status; } } } }
sorry jumble rather long support code. anyways, void refresh()
called dispatchertimer (which isn't shown), starts refreshworker.runworkerasync(this.computerlist);
.
i've been fighting few days i'm point i'm not attempting modify objects referenced in observablecollection
directly anymore. hence ugly looping through computerlist collection , setting properties directly.
any idea whats going on here , how can fix it?
the observablecollection wont fire when change properties of items inside of collection (how should know that). observablecollection fires when list gets changed (added, exchanged, removed).
if want detect changes of properties of computerentry class has implement inotifypropertychange interface (if know mvvm, lightweight mvvm pattern)
public class computerentry : inotifypropertychanged { #region inotifypropertychanged members public event propertychangedeventhandler propertychanged; #endregion private void raisepropertychanged(string propertyname) { if (this.propertychanged != null) { this.propertychanged(this, new propertychangedeventargs(propertyname)); } } private string _computername; public string computername { { return _computername; } set { if (_computername != value) { _computername = value; this.raisepropertychanged("computername"); } } } }
Comments
Post a Comment