Reputation: 91
I'm writing a client/server WinForms application in C# using VS 2015.
I have a ListBox control whose DrawItem event is owner-drawn (yes, I set the DrawMode property to OwnerDrawFixed), which has to be redrawn every time a new message is recieved.
I use this callback following this reference:
private void chatLobby_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
int ItemMargin = 0;
string last_u = "";
foreach(Message m in ChatHistory[activeChatID])
{
// Don't write the same user name
if(m.from.name != last_u)
{
last_u = m.from.name;
e.Graphics.DrawString(last_u, ChatLobbyFont.Username.font, ChatLobbyFont.Username.color, e.Bounds.Left, e.Bounds.Top + ItemMargin);
ItemMargin += ChatLobbyFont.Message.font.Height;
}
e.Graphics.DrawString(" " + m.message, ChatLobbyFont.Message.font, ChatLobbyFont.Message.color, e.Bounds.Left, e.Bounds.Top + ItemMargin);
ItemMargin += ChatLobbyFont.Message.font.Height;
}
e.DrawFocusRectangle();
}
And this is the MeasureItem method:
private void chatLobby_MeasureItem(object sender, MeasureItemEventArgs e)
{
// No messages in the history
if(ChatHistory[activeChatID][0] == null)
{
e.ItemHeight = 0;
e.ItemWidth = 0;
}
string msg = ChatHistory[activeChatID][e.Index].message;
SizeF msg_size = e.Graphics.MeasureString(msg, ChatLobbyFont.Message.font);
e.ItemHeight = (int) msg_size.Height + 5;
e.ItemWidth = (int) msg_size.Width;
}
The message is recieved and inserted using ListBox.Add()
and it does work, confirmed by the debugger.
But the ListBox redraws only when I click it (I think it fires a focus).
I already tried .Update()
, .Refresh()
and .Invalidate()
with no luck.
Is there a way to trigger DrawItem()
from code?
Upvotes: 1
Views: 2044
Reputation: 91
After some research, I found the solution: the DrawItem event is called when the control gets altered.
As a matter of fact, .Add()
does the trick.
I changed my update function with this:
private void getMessages()
{
// ... <--- connection logic here
chatLobby.Items.Add(" "); // Alters the listbox
}
Upvotes: 1