我一直在敲打WPF ListBox项目绑定几个小时,我希望得到一些建议。我的申请有三个主要内容:
Player
发送和接收数据的TcpClient
类。MainWindow
,用于处理GUI并公开Player
可以调用的方法,以提供基于网络消息更新UI的数据。UserControl
的{{1}}包含1)名为HostLobby
的{{1}},用于显示客户通过ListBox
和2)添加的新游戏用于添加要向所有客户广播的新游戏的UI元素。我已确认“上游”部分有效。您可以在gamesListBox
上输入新的游戏信息,提交,并按预期传播给客户。此外,客户端正确响应服务器消息,告诉他们已添加新游戏。
问题是,我无法更新Player
。我在HostLobby
控件和gameListBox
上绑定了测试按钮以验证绑定是否正常工作 - 它是什么。我似乎无法通过从HostLobby
传递数据来更新。我有什么想法吗?
相关代码:
Player.cs
MainWindow
MainWindow.cs
Player
HostLobby.cs
public void AddGameToLobby(string name, int mp)
{
// name and mp are provided by the network message handler and work fine
WriteToLog("Attempting to add game to host lobby", true);
mainWindow.AddGameToLobby(name, mp);
}
HostLobby.xaml
public void AddGameToLobby(string n, int mp)
{
hostLobby.AddGameToList(n, mp);
}
答案 0 :(得分:1)
您的ListBox
未更新,因为您正在修改工作线程上的ObservableCollection
,这意味着正在工作线程上引发集合的CollectionChanged
事件。要解决此问题,您需要在UI线程上修改列表。要实现这一目标,您有几个选择,但首先想到的是:
使用Dispatcher.BeginInvoke
在AddGameToList
的{{1}}中,将修改列表的语句放在HostLobby.cs
中:
Dispatcher.BeginInvoke
使用BindingOperations.EnableCollectionSynchronization(.NET 4.5或更高版本)
首先,创建一个锁定对象作为Application.Current.Dispatcher.BeginInvoke((MethodInvoker)(() => games.Add(new Game() { Name = msg })));
类的私有成员。然后,在初始化HostLobby
后,请调用以下内容:
ObservableCollection
然后,每当您修改BindingOperations.EnableCollectionSynchronization(games, _yourLockObj);
中的列表时,请使用锁定。因此,在这种情况下,您需要更改HostLobby
中的列表修改,以便它使用锁:
AddGameToList
在我看来,后者似乎是一个更好的选择,但只有在使用.NET 4.5或更高版本时它才可用。