报错背景
在一个新WPF项目中显示加载界面显示进度条和消息。用于封装消息和进度条值的 LoadModel 的loadmsg 属性的数据类型由LeoObservableCollection<string> 改成了ObservableCollection<string>,在界面上执行
Application.Current.Dispatcher.Invoke(new Action(() =>
{
Global._loadIns.LoadMsg.Add(message);
Global._loadIns.LoadProcess = loadProcessVal;
}));
代码时发生报错
1.报错图
2.相关代码
/// <summary>
/// 加载 模型
/// </summary>
public class LoadModel : ViewModelBase
{
public LoadModel()
{
// ObservableCollection
LoadMsg = new LeoObservableCollection<string>();
LoadProcess = 0;
}
//private ObservableCollection<string> loadmsg;
private LeoObservableCollection<string> loadmsg;
/// <summary>
/// 加载时的 消息
/// </summary>
public LeoObservableCollection<string> LoadMsg
{
get => loadmsg;
set
{
loadmsg = value;
RaisePropertyChanged("LoadMsg");
}
}
private float loadprocess;
/// <summary>
/// 进度条
/// </summary>
public float LoadProcess
{
get => loadprocess;
set
{
loadprocess = value;
RaisePropertyChanged("LoadProcess");
}
}
}
3.解决方法
3.1 方法1
private ObservableCollection<string> loadmsg; 集合还是使用 ObservableCollection 集合时。 修改界面上代码,首先在 构造中增加DispatcherHelper.Initialize(); SetLoadMsg 方法如下修改
/// <summary>
/// 设置加载消息
/// </summary>
/// <param name="message">显示消息</param>
/// <param name="loadProcessVal">进度条数值</param>
public static void SetLoadMsg(string message, float loadProcessVal)
{
//System.NotSupportedException:“该类型的 CollectionView 不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改。”
//这个报错和ObservableCollection这个集合有关,ObservableCollection这个集合是线程安全集合默认是不能进行跨线程访问的,如果出现跨线程访问就是报上面的错
//报错解决方法
//方法1.用task启动一个线程,具体代码如下
Task.Run(() => DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
Global._loadIns.LoadMsg.Add(message);
Global._loadIns.LoadProcess = loadProcessVal;
}));
}
代码结图
3.2 方法2 只改LoadModel的loadmsg属性的数据类型为LeoObservableCollection
具体看上面LoadModel的代码
配合原来的界面代码
/// <summary>
/// SplashWindow.xaml 的交互逻辑
/// </summary>
public partial class SplashWindow : Window
{
public SplashWindow()
{
InitializeComponent();
DataContext = Global._loadIns;
}
/// <summary>
/// 设置加载消息
/// </summary>
/// <param name="message">显示消息</param>
/// <param name="loadProcessVal">进度条数值</param>
public static void SetLoadMsg(string message, float loadProcessVal)
{//方法2.LoadMsg集合的类型ObservableCollection这个集合用LeoObservableCollection这个替换
Application.Current.Dispatcher.Invoke(new Action(() =>
{
Global._loadIns.LoadMsg.Add(message);
Global._loadIns.LoadProcess = loadProcessVal;
}));
}
}