从工作线程刷新 DataGrid
Refresh DataGrid from worker thread
我的 WPF 应用程序中有一个 DataGrid。对于这个 DataGrid,我已将 ItemSource 设置如下
ItemsSource="{Binding Path=MyItems}"
MyItems 是在 MyViewModel 中声明的 MyItem 列表
// ItemsSource for MyItem Grid
public List<MyItem> MyItems {get;set; }
MyItem 有一组属性,每个 属性 都映射到 DataGrid 中的每一列。在初始化时,我正在填充 MyItems;因此 DataGrid 在每列中显示 MyItems 值。
在按钮命令中,我正在创建一个工作线程,工作线程修改网格中显示的 MyItems 的属性。例如,MyItem 有一个名为 "Status" 的 属性,它绑定到一列网格。状态值在工作线程中更改。我调用的工作线程结束
OnPropertyChanged("MyItems"); //force UI refresh
但是网格中的状态列值没有更新。
单击数据网格列后,只有值在刷新。如何从工作线程刷新数据网格?
如果操作正确,您将不需要告诉网格刷新。如果您确实设法刷新了整个网格,也会出现意想不到的后果,例如跳到网格顶部并丢失任何选定的用户 rows/cells 以及中止编辑(如果适用)。
ObservableCollection
这是设置网格正在查看的列表的方式:
private readonly ObservableCollection<MyItem> _myItems = new ObservableCollection<MyItem>();
public IEnumerable<MyItem> MyItems { get { return _myItems; } }
这意味着新项目和移除会自动更新网格。然而,要更新单个单元格,属性 需要是可观察的,即 class MyItem
必须实现 INotifyPropertyChanged
.
多线程
对于多线程,您需要在 UI 线程中设置 MyItem
的属性,即使您在辅助线程中进行计算(见下文)也是如此。您可以使用 Dispatcher
. See Updating GUI (WPF) using a different thread
工作线程
至于启动你自己的线程,不要那样做,使用 Task
。
使用调度程序不是一个好主意。 UI 如果编码不当,可能会变得无响应。在多线程环境中使用数据网格很棘手。
- 后台线程处理数据并根据这个结果
处理,数据网格将被更新。
- UI WPF 中的控件只能由 UI 线程更新。
- 可以有多个 UI 控件一起工作
实现整体功能(进度条、按钮等)。
编码人员经常错误地在
不安全的方式。
- 数据网格将绑定到的数据源不应该是
可由任何其他 class.
修改
我在这里发布了一个模板。它涵盖了在多线程设置中使用数据网格的可能方法。
http://www.codeproject.com/Articles/1086714/A-Template-For-Using-Datagrid-in-Monitoring-UI
我的 WPF 应用程序中有一个 DataGrid。对于这个 DataGrid,我已将 ItemSource 设置如下
ItemsSource="{Binding Path=MyItems}"
MyItems 是在 MyViewModel 中声明的 MyItem 列表
// ItemsSource for MyItem Grid
public List<MyItem> MyItems {get;set; }
MyItem 有一组属性,每个 属性 都映射到 DataGrid 中的每一列。在初始化时,我正在填充 MyItems;因此 DataGrid 在每列中显示 MyItems 值。
在按钮命令中,我正在创建一个工作线程,工作线程修改网格中显示的 MyItems 的属性。例如,MyItem 有一个名为 "Status" 的 属性,它绑定到一列网格。状态值在工作线程中更改。我调用的工作线程结束
OnPropertyChanged("MyItems"); //force UI refresh
但是网格中的状态列值没有更新。
单击数据网格列后,只有值在刷新。如何从工作线程刷新数据网格?
如果操作正确,您将不需要告诉网格刷新。如果您确实设法刷新了整个网格,也会出现意想不到的后果,例如跳到网格顶部并丢失任何选定的用户 rows/cells 以及中止编辑(如果适用)。
ObservableCollection
这是设置网格正在查看的列表的方式:
private readonly ObservableCollection<MyItem> _myItems = new ObservableCollection<MyItem>();
public IEnumerable<MyItem> MyItems { get { return _myItems; } }
这意味着新项目和移除会自动更新网格。然而,要更新单个单元格,属性 需要是可观察的,即 class MyItem
必须实现 INotifyPropertyChanged
.
多线程
对于多线程,您需要在 UI 线程中设置 MyItem
的属性,即使您在辅助线程中进行计算(见下文)也是如此。您可以使用 Dispatcher
. See Updating GUI (WPF) using a different thread
工作线程
至于启动你自己的线程,不要那样做,使用 Task
。
使用调度程序不是一个好主意。 UI 如果编码不当,可能会变得无响应。在多线程环境中使用数据网格很棘手。
- 后台线程处理数据并根据这个结果 处理,数据网格将被更新。
- UI WPF 中的控件只能由 UI 线程更新。
- 可以有多个 UI 控件一起工作 实现整体功能(进度条、按钮等)。 编码人员经常错误地在 不安全的方式。
- 数据网格将绑定到的数据源不应该是 可由任何其他 class. 修改
我在这里发布了一个模板。它涵盖了在多线程设置中使用数据网格的可能方法。
http://www.codeproject.com/Articles/1086714/A-Template-For-Using-Datagrid-in-Monitoring-UI