I am using MonoMac to build a desktop download manager for Mac in C#.
My XIB has a Table View, whose columns are bound to an NSArrayController
. The array controller is connected to my Main Window Controller through an IBOutlet
. The array holds a bunch of HttpDownload
objects, which derive from NSObject
. These HttpDownload
objects contain properties such as TotalSize
, TotalDownloaded
, Bandwidth
, etc. I have decorated these properties with an [Export]
attribute.
In the controller I add some HttpDownload objects to the NSArrayController
using the AddObject
method. A background process, started with Task.Factory.StartNew()
begins the download asynchronously and updates the bound properties such as TotalDownloaded and Bandwidth as data is received.
I can see these new values being reflected in the Table View, but only once I've "forced" a UI update, for instance by causing the window to lose focus, gain focus, or by clicking on a button within the window.
I have tried setting Continuously Updates Value in IB, but this makes no difference (and reading the docs, I didn't think it should).
Does anyone know to make the UI update the bound values in "real time", instead of only when a window event occurs?
I figured this out shortly after I posted this question.
It seems that we need to manually call WillChangeValue()
and DidChangeValue()
for at least one of the keys that are being updated, for instance, when I updated the total downloaded:
WillChangeValue("DownloadedBytes");
DownloadedBytes += bytesRead;
DidChangeValue("DownloadedBytes");
In my case, calling these methods for just one of the updated keys seems to be enough to force an update of all the bound values.
For reference, in Objective-C these selectors are called [self willChangeValueForKey:@"keyname"]
and [self didChangeValueForKey:@"keyname"]
.