How to update the view after the model has changed?

enzom83

Say I have a Logger class, a LoggerViewModel class and a MainWindow with a TextBox. The Logger class is a thread-safe singleton, so I have only an instance of it in the 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
    {
        get { 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
    {
        get
        {
            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 is updated by more thread while the application is running, so I would update the TextBox on the MainWindow whenever the model (that is the Logger singleton class) changes.

How to connect the Model and the ViewModel between them? I emphasize that the Model is changed by only a few application thread, so it is read-only from the point of view of UI.

I provided the LoggerText property within the LoggerViewModel class, since I thought the following working mechanism. 1. When the Model (the Logger instance) changes, it notifies the ViewModel. 2. The ViewModel receives the notify by the Model and create a new string containing all the messages from the logger. 3. The ViewModel notifies the View.

public class LoggerViewModel : INotifyPropertyChanged
{
    Logger _LoggerModel;

    /// <summary>
    /// 
    /// </summary>
    public LoggerViewModel()
    {
        _LoggerModel = Logger.Instance;
    }

    /// <summary>
    /// 
    /// </summary>
    public string LoggerText
    {
        get
        {
            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 a copy to prevent thread issues
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

How the ViewModel can intercept the notifications sent by the Model?

Jakob Christensen

First of all I do not like that you are using a singleton. When using the singleton pattern you are making it hard on yourself when testing or reusing your view controllers. I would instead inject the Logger dependency into your LoggerViewModel class.

Aside from that one way to solve your problem is to register a handler for the PropertyChanged event on your Logger and build the text when the event fires for the Entries property.

In LoggerViewModel you would then add a property handler and update the LoggerText property as 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 for 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");
    }

    get
    {
        return _loggerText;
    }
}

Disclaimer: The above code is written without a compiler.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to update the view after the model has changed?

From Dev

How to correctly update the Model after the ViewModel has changed?

From Dev

How to check if my model has changed on the view?

From Dev

How to refresh controls after a model has changed?

From Dev

How to update AngularJS view when the value has not changed?

From Dev

How to update the view after changing the model in Angular?

From Dev

how to load libsvm model in java after serialVersionUID has changed

From Dev

QtQuick - make TableView update its rowCount after its model has changed

From Dev

Trigger a view to render after model changed

From Dev

How update model after inserting entry to database? And refresh a view

From Dev

How to check if any attribute has changed on a model

From Dev

How to check if any attribute has changed on a model

From Dev

How to tell if user changed a property in the view model

From Dev

How to update a row on parent table after child table has been changed

From Dev

How to update a dbSet if the record has changed in the database?

From Dev

Refresh view when model data has not changed (Qt/PySide/PyQt)?

From Dev

SAPUI5 refresh binding / model after path has changed

From Dev

SAPUI5 refresh binding / model after path has changed

From Dev

Update View/Model after "reset" in ember

From Dev

How to update colors after vertex colors are changed?

From Dev

How to update colors after vertex colors are changed?

From Dev

Model instances not flagged as changed after successful attribute update

From Dev

How to update model and view model in MVVM pattern?

From Dev

How to update view model data from another view model in Knockout

From Dev

How to detect if a file has changed in a model save function

From Dev

Qt Model-View: What's the correct way to update the model and then the view when the data is stored and changed outside the model in a std::vector

From Dev

How to inform the model/view that underlying data changed table headers?

From Dev

JavaFx how can my model update View?

From Dev

Has the update process changed in 16.04?

Related Related

  1. 1

    How to update the view after the model has changed?

  2. 2

    How to correctly update the Model after the ViewModel has changed?

  3. 3

    How to check if my model has changed on the view?

  4. 4

    How to refresh controls after a model has changed?

  5. 5

    How to update AngularJS view when the value has not changed?

  6. 6

    How to update the view after changing the model in Angular?

  7. 7

    how to load libsvm model in java after serialVersionUID has changed

  8. 8

    QtQuick - make TableView update its rowCount after its model has changed

  9. 9

    Trigger a view to render after model changed

  10. 10

    How update model after inserting entry to database? And refresh a view

  11. 11

    How to check if any attribute has changed on a model

  12. 12

    How to check if any attribute has changed on a model

  13. 13

    How to tell if user changed a property in the view model

  14. 14

    How to update a row on parent table after child table has been changed

  15. 15

    How to update a dbSet if the record has changed in the database?

  16. 16

    Refresh view when model data has not changed (Qt/PySide/PyQt)?

  17. 17

    SAPUI5 refresh binding / model after path has changed

  18. 18

    SAPUI5 refresh binding / model after path has changed

  19. 19

    Update View/Model after "reset" in ember

  20. 20

    How to update colors after vertex colors are changed?

  21. 21

    How to update colors after vertex colors are changed?

  22. 22

    Model instances not flagged as changed after successful attribute update

  23. 23

    How to update model and view model in MVVM pattern?

  24. 24

    How to update view model data from another view model in Knockout

  25. 25

    How to detect if a file has changed in a model save function

  26. 26

    Qt Model-View: What's the correct way to update the model and then the view when the data is stored and changed outside the model in a std::vector

  27. 27

    How to inform the model/view that underlying data changed table headers?

  28. 28

    JavaFx how can my model update View?

  29. 29

    Has the update process changed in 16.04?

HotTag

Archive