I have a list view bound to an ObservableCollection. With that I want to mock a chat application with a WPF gui.
To simulate some activity I wanted to use a Background worker who spams a little bit. But the worker always exits his loop after executing the first statment, so my question is: why does he do that and how to fix it?
here is the code so far:
public partial class MainWindow : Window, INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private string pCurrentUsername;
public string currentUsername
{
get { return pCurrentUsername; }
set
{
pCurrentUsername = value;
if (null != this.PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs("currentUsername"));
}
}
}
ObservableCollection<ChatPost> items = new ObservableCollection<ChatPost>();
BackgroundWorker bgWorker = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
currentUsername = "Me";
items.Add(new ChatPost("this", "that"));
bgWorker.DoWork += new DoWorkEventHandler(mockBussiness);
bgWorker.RunWorkerAsync();
lvChat.ItemsSource = items;
}
private void mockBusiness(object o, DoWorkEventArgs args)
{
while (!bgWorker.CancellationPending)
{
items.Add(new ChatPost("guy1", "Ey man!"));
items.Add(new ChatPost("guy2", "What man?"));
}
}
private void btSend_Click(object sender, RoutedEventArgs e)
{
items.Add(new ChatPost(currentUsername, tbMessage.Text));
}
}
public class ChatPost
{
public ChatPost()
{ }
public ChatPost(string username, string message)
{
this.username = username;
this.message = message;
}
public string username { get; set; }
public string message { get; set; }
}
So the only thing that gets executed (meaning printed) is one time "Ey man!"
Yes, you're modifying the UI (indirectly, through the ObservableCollection<>
) on a non-UI thread. You're not allowed to do that. I suspect you should find an exception being thrown giving that detail, although it may not be easy to find.
You need to marshal back to the UI thread for any threading operations, in general. If you're using WPF on .NET 4.5, apparently you can using BindingOperations.EnableCollectionSynchronization
for this, but I admit I have no direct experience of this.
See more on this question at Stackoverflow