WPF从不同类中调用的方法更新ListBox项

时间:2018-05-30 15:25:54

标签: c# wpf data-binding

我一直在敲打WPF ListBox项目绑定几个小时,我希望得到一些建议。我的申请有三个主要内容:

  1. 通过Player发送和接收数据的TcpClient类。
  2. 一个MainWindow,用于处理GUI并公开Player可以调用的方法,以提供基于网络消息更新UI的数据。
  3. 名为UserControl的{​​{1}}包含1)名为HostLobby的{​​{1}},用于显示客户通过ListBox和2)添加的新游戏用于添加要向所有客户广播的新游戏的UI元素。
  4. 我已确认“上游”部分有效。您可以在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);
    }
    

1 个答案:

答案 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或更高版本时它才可用。