网站建设 策划方案书,网站负责人可以备案,查公司资质在哪个网站,屏蔽 wordpress 插件下载解决 WPF 绑定集合后数据变动界面却不更新的问题独立观察员 2020 年 9 月 9 日在 .NET Core 3.1 的 WPF 程序中打算用 ListBox 绑定显示一个集合#xff08;满足需求即可#xff0c;无所谓什么类型的集合#xff09;#xff0c;以下是 Xaml 代码#xff08;瞟一眼就行满足需求即可无所谓什么类型的集合以下是 Xaml 代码瞟一眼就行不是本文讨论重点ListBox ItemsSource{Binding SipRegistrations, ModeOneWay} SelectedValue{Binding SelectedAccountBinding, ModeOneWayToSource}ListBox.ItemTemplateDataTemplateTextBlock Text{Binding SIPAccount.SIPUsername}/TextBlock/DataTemplate/ListBox.ItemTemplate
/ListBoxViewModel 中有一个目标集合当前是一个 List。属性变动通知有两种实现方式一是使用 PropertyChanged.Fody二是使用自定义绑定基类 BindableBase如下图。 下面主要谈论数据变动集合增加内容后前台的界面却没有更新的问题。具体来说就是List.Add 之后第一次有效果但后面就没效果了界面始终只显示一条数据。 原始无效果SipRegistrations.RemoveAll(x x.SIPAccount.SIPUsername sipAccount.SIPUsername); // 移除重复项如果有的话
SipRegistrations.Add(binding); // 添加新项
猜想是因为 List 的引用并没有变化所以被认为该属性没有改变进而也就没有变动通知。其实这种需要变动通知的情况推荐使用的是 ObservableCollection 但是本人之前使用 ObservableCollection 没有成功过反而是使用 List 是可以的所以还是先看看用 List 怎么解决吧。 变体一调试时有几率有效果// 添加联系人到集合并处理界面绑定
SipRegistrations.RemoveAll(x x.SIPAccount.SIPUsername sipAccount.SIPUsername);
ListSIPAccountBinding tempList SipRegistrations; // 临时集合
SipRegistrations new ListSIPAccountBinding(); // 目标集合先置为空
tempList.Add(binding); // 临时集合添加新项
SipRegistrations tempList; // 临时集合赋值给目标集合
变体一通过临时变量做中转强制让目标集合的引用发生改变但结果是只在调试时以很小的概率成功过。由于这部分代码是在异步逻辑里所以有可能是在多线程环境而 List 不是线程安全的所以有了以下加锁版本的变体二。 变体二无效果应该是和变体一类似#region 成员/// summary
/// 加锁对象
/// /summary
private object _lockObj new object();#endregion// 加锁
lock (_lockObj)
{// 添加联系人到集合并处理界面绑定SipRegistrations.RemoveAll(x x.SIPAccount.SIPUsername sipAccount.SIPUsername);ListSIPAccountBinding tempList SipRegistrations;SipRegistrations new ListSIPAccountBinding();tempList.Add(binding);SipRegistrations tempList;
}加了锁还是不行不过锁还是需要的又想到既然调试的时候有几率成功那么是不是和代码运行速度有关呢于是在目标集合置空和重新赋值之间加了个线程休眠竟然真的可以也就是以下的变体三。 变体三有效果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 ObservableCollectionSIPAccountBinding SipRegistrations { get; set; } new ObservableCollectionSIPAccountBinding();#endregionlock (_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