1

I am using gui.cs.

I have a ListView that shows network nodes. These nodes come and go so the list gets updated on the right events.

var clients = new List<Node>();
var clientList = new ListView(clients)
{
    Height = Dim.Fill(),
    Width = Dim.Fill(),
};

server.NodeJoined += (s, e) =>
{
    clients.Add(e.Node);
    Application.Refresh();
};

server.NodeLeft += (s, e) =>
{
    var client = clients.FirstOrDefault(n => n.IP == e.Node.IP);
    if (client != null) clients.Remove(client);
    Application.Refresh();
};

Currently I'm using the Application.Refresh() which updates the whole UI. Ideally only the changed parts should be updated. Is this correct or is there a better way to inform ListView that the data source has changed and it needs a redraw?

Mara09
  • 65
  • 6
  • *Ideally only the changed parts should be updated* => This notion becomes buggy as simple UI becomes complex with inter-related data, like, the real world. A thick web of event handling plus many (it's only simple ones!) data field rules in the UI - and thus left out of the business model, are root causes. – radarbob May 03 '22 at 20:54
  • Looking at the [API Reference](https://migueldeicaza.github.io/gui.cs/api/Terminal.Gui/Terminal.Gui.html) for that project, I see a [`Redraw`](https://migueldeicaza.github.io/gui.cs/api/Terminal.Gui/Terminal.Gui.View.html#Terminal_Gui_View_Redraw_Terminal_Gui_Rect_) function that says to always use the [`Bounds`](https://migueldeicaza.github.io/gui.cs/api/Terminal.Gui/Terminal.Gui.View.html#Terminal_Gui_View_Bounds) property. Dunno if that will work, never used that project before, but it seems promising. – Joshua Robinson May 03 '22 at 21:12

1 Answers1

1

The correct way to make UI changes from a callback is to use MainLoop.Invoke. If you do that then you can simply call SetNeedsDisplay on your View.

The Invoke ensures that list content changes don't occur while the view is rendering and means that SetNeedsDisplay is immediately detected and the redraw occurs.

ListView clientList = new ListView();
Application.MainLoop.Invoke(()=>
{
    // TODO: Change list contents here

    // Tell view to redraw
    clientList.SetNeedsDisplay();
});
Thomas N
  • 623
  • 1
  • 4
  • 14