c# - How to update the view after the model has changed? -
say have logger
class, loggerviewmodel
class , mainwindow
textbox
. logger
class thread-safe singleton, have instance of in application domain.
public sealed class logger : inotifypropertychanged { private static readonly logger _instance = new logger(); private static readonly object _synclock = new object(); private static list<logentry> _data = new list<logentry>(); /// <summary> /// /// </summary> private logger() { ; } /// <summary> /// /// </summary> public static logger instance { { return _instance; } } /// <summary> /// /// </summary> /// <param name="entry"></param> public void write(logentry entry) { lock (_synclock) { _data.add(entry); } this.raisenotifypropertychanged("entries"); } /// <summary> /// /// </summary> /// <param name="component"></param> /// <param name="message"></param> public void write(string component, string message) { logentry entry = logentry.create(component, message); write(entry); } /// <summary> /// /// </summary> public ilist<logentry> entries { { lock (_synclock) { return new readonlycollection<logentry>(_data); } } } /// <summary> /// /// </summary> /// <param name="property"></param> private void raisenotifypropertychanged(string property) { var handler = propertychanged; if (handler != null) { handler(this, new propertychangedeventargs(property)); } } /// <summary> /// /// </summary> public event propertychangedeventhandler propertychanged; }
the logger
unique instance updated more thread while application running, update textbox
on mainwindow
whenever model (that logger
singleton class) changes.
how connect model , viewmodel between them? emphasize model changed few application thread, read-only point of view of ui.
i provided loggertext
property within loggerviewmodel
class, since thought following working mechanism. 1. when model (the logger
instance) changes, notifies viewmodel. 2. viewmodel receives notify model , create new string
containing messages logger. 3. viewmodel notifies view.
public class loggerviewmodel : inotifypropertychanged { logger _loggermodel; /// <summary> /// /// </summary> public loggerviewmodel() { _loggermodel = logger.instance; } /// <summary> /// /// </summary> public string loggertext { { string text = ""; list<logentry> entries = new list<logentry>(_loggermodel.entries); foreach (logentry entry in entries) { text += entry.tostring(); text += "\n"; } return text; } } public event propertychangedeventhandler propertychanged; private void raisepropertychanged(string propertyname) { // take copy prevent thread issues propertychangedeventhandler handler = propertychanged; if (handler != null) { handler(this, new propertychangedeventargs(propertyname)); } } }
how viewmodel can intercept notifications sent model?
first of not using singleton. when using singleton pattern making hard on when testing or reusing view controllers. instead inject logger
dependency loggerviewmodel
class.
aside 1 way solve problem register handler propertychanged
event on logger
, build text when event fires entries
property.
in loggerviewmodel
add property handler , update loggertext
property needed.
public loggerviewmodel(logger loggermodel /* dependency injection*/) { _loggermodel = loggermodel; _loggermodel.propertychanged += this.loggermodel_propertychanged; } private void loggermodel_propertychanged(object sender, propertychangedeventargs args) { if (args.propertyname == "entries") { stringbuilder text = new stringbuilder(); // use stringbuilder performance list<logentry> entries = new list<logentry>(_loggermodel.entries); foreach (logentry entry in entries) { text.appendline(entry.tostring()); } this.loggertext = text.tostring(); } } private string _loggertext; public string loggertext { set { _loggertext = value; raisepropertychanged("loggertext"); } { return _loggertext; } }
disclaimer: above code written without compiler.
Comments
Post a Comment