WPF--DataGrid的ItemSource与其项源不一致而出错,问题记录及解决

1.出现的问题

1、报错代码和位置

  Message	"该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。"	

在这里插入图片描述

2.我的思路

1、解决背景

在MainViewModel 中 有一个 DataGrid 的 ItemSource 类型为 以下

private ObservableCollection<Log> _Logs;

public ObservableCollection<Log> Logs
{
    get { return _Logs; }
    set { SetProperty(ref _Logs, value); }
}

在下面这个类里面我定义了 一个事件 、事件触发方法,并且事件传递 事件数据Log。

namespace WSTVirtualRobot.Common.Log
{
    public class LogOperate
    {
        public event PubLogDelegate LogEvent;

        public void UpdateLog(object sender, Log log)
        {
            LogEvent?.Invoke(sender, log);
        }
    }
    public delegate void PubLogDelegate(object obj, Log log);
}

在App.xaml 中我注册了 LogOperate,以便项目中其他类需要记录日志,通过构造函数获取LogOperate 实例,调用方法 UpdateLog,触发事件。以下所示

在这里插入图片描述

在MinViewModel 的构造函数中 获取 LogOperate 实例,并且我订阅了 日志事件,如下:
在这里插入图片描述
编写事件处理方法AddLog, 在AddLog 方法里面,我对集合 DataGrid 的 ItemSource 类型的bservableCollection Logs 进行元素添加。这里我期望实现的功能是,其他类想要记录日志的时候,都会将日志 通过 LogEvent 发送给事件处理程序 AddLog, 将新出现的日志显示到主界面。
在这里插入图片描述

到这里我所有的类和方法都基本实现了,接下来就是在其他类里面记录日志,看是否会在界面显示了。

在我的TCPServer 类里面 ,有一个监听线程里面,记录了日志
在这里插入图片描述

运行结果出现了开头的错误。错误如下:Message “该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。”

2、解决方式1

出现了问题 当然得解决呀,WPF 框架里面专门有一个Dispatcher 类 专门有用来管理和调度UI线程。
于是我想获取当前应用程序的Dispatcher 来 更新Log。于是我将调用Dispater的方法调用在监听线程里面,去调度UI。

在这里插入图片描述

问题记录

报错位置和类型,报错出现在 App基类上。报:System.InvalidOperationException
HResult=0x80131509
Message=某个 ItemsControl 与它的项源不一致。\n请参见内部异常以获取更多信息。
Source=PresentationFramework
StackTrace:
在 System.Windows.Controls.ItemContainerGenerator.Verify()
在 System.Windows.Controls.VirtualizingStackPanel.MeasureChild(IItemContainerGenerator& generator, IContainItemStorage& itemStorageProvider, IContainItemStorage& parentItemStorageProvider, Object& parentItem, Boolean& hasUniformOrAverageContainerSizeBeenSet, Double& computedUnif

在这里插入图片描述
ItemsControl 数据项与他的位置不一致。

3、解决方式2

网上查了各种,都是上面的解决方式,我的头都要大了!!!

后来我一个一个打断点调式,发现: 在哪个线程触发的事件,哪个线程就处理订阅了该事件的方法,所以 监听线程触发了UpdateLog 事件,监听线程处理订阅了该事件的方法。
不应该将触发事件的方法写在 dispatcher 里面,注意这里Dispather 处理与UI有关的部分,
所以这里我转变思路,Dispather 写在 订阅了UpdateLog 事件的事件处理程序 AddLog 里面。 因为这里面是将ItemSource Item 产生变化的地方,虽然可能像其他线程也会触发日志事件,但Dispather 会将UI线程里面的Source 更新,从而显示到界面上去。

问题解决:
在这里插入图片描述
在这里插入图片描述
到此问题已得到解决。哈哈哈,开心 !

3.总结复盘

出现这样的问题主要在于,在WPF 中 对UI 线程的调度不是很理解。
通过这个小项目的编写和调式对Dispatcher 类 有了一定的认识和学习。
当然了也对Prism 框架的依赖注入的使用和理解不到位,还需要多应用多练习和调式。
通过这个项目我也获得了一些收获,对事件和委托的应用掌握得更熟练,对依赖注入其中的单例模式的应用有了一定的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值