加了锁还是不行(不过锁还是需要的),又想到,既然调试的时候有几率成功,那么是不是和代码运行速度有关呢?于是在目标集合置空和重新赋值之间加了个线程休眠,竟然真的可以,也就是以下的变体三。
lock (_lockObj)
//添加联系人到集合并处理界面绑定;
SipRegistrations.RemoveAll(x => x.SIPAccount.SIPUsername == sipAccount.SIPUsername);
List tempList = SipRegistrations;
SipRegistrations = new List();
Thread.Sleep(500); //关键代码;
tempList.Add(binding);
SipRegistrations = tempList;
好了,以上就是解决方法了。
接下来再尝试一下 ObservableCollection 吧:
#region 成员
/// <summary>
/// 加锁对象
/// </summary>
private object _lockObj = new object();
public ObservableCollection<SIPAccountBinding> SipRegistrations { get; set; } = new ObservableCollection<SIPAccountBinding>();
#endregion
lock (_lockObj)
SipRegistrations.Remove(SipRegistrations.FirstOrDefault(x => x.SIPAccount.SIPUsername == sipAccount.SIPUsername));
SipRegistrations.Add(binding); //情况一
//SipRegistrations.Append(binding); //情况二
Console.WriteLine($"注册联系人 [{binding.RegisteredContact}] 为 [{sipAccount.SIPUsername}].");
这个有两种情况(都不能成功):
情况一,使用 Add 方法,结果是执行完 Add 方法后就返回了,后面的方法不再执行(不知道为什么),界面上是有几率能添加一条。
情况二,使用 Append 方法,执行完 Append 后倒是可以继续执行后面的代码,但是界面上一条也出现不了。
后记:本文主要是抛砖引玉,大家有什么更好的方法,或者能解释文中所描述现象的原理,请不吝赐教。
项目地址:https://gitee.com/DLGCY_GB28181/SimpleSIPServer
经过在 https://dotnet9.com/ 站长的技术讨论群的讨论,决定还是要使用 ObservableCollection。加上在网上搜到了文章《WPF ViewModel 中对 ObservableCollection 集合操作》,所以最终代码为:
#region 成员
/// <summary>
/// 加锁对象
/// </summary>
private object _lockObj = new object();
/// <summary>
/// 集合对象
/// </summary>
public ObservableCollection<SIPAccountBinding> SipRegistrations { get; set; } = new ObservableCollection<SIPAccountBinding>();
#endregion
lock (_lockObj)
ThreadPool.QueueUserWorkItem(delegate
SynchronizationContext.SetSynchronizationContext(new System.Windows.Threading.DispatcherSynchronizationContext(Application.Current.Dispatcher));
SynchronizationContext.Current?.Post(pl =>
SipRegistrations.Remove(SipRegistrations.FirstOrDefault(x => x.SIPAccount.SIPUsername == sipAccount.SIPUsername));
SipRegistrations.Add(binding);
}, null);
Console.WriteLine($"注册联系人 [{binding.RegisteredContact}] 为 [{sipAccount.SIPUsername}].");
甚至还可以简化:
Application.Current.Dispatcher.Invoke(delegate
SipRegistrations.Remove(SipRegistrations.FirstOrDefault(x => x.SIPAccount.SIPUsername == sipAccount.SIPUsername));
SipRegistrations.Add(binding);
原创文章,转载请注明: 转载自 独立观察员(dlgcy.com)
本文链接地址: [解决 WPF 绑定集合后数据变动界面却不更新的问题](https://dlgcy.com/wpf-binding-list-update/)
关注微信公众号 独立观察员博客(DLGCY_BLOG) 第一时间获取最新文章