更改源时DataGrid更新不起作用
Posted
技术标签:
【中文标题】更改源时DataGrid更新不起作用【英文标题】:DataGrid update not working when changed source 【发布时间】:2022-01-20 02:36:16 【问题描述】:这是我的 DataGrid 测试代码。我使用 ObservableCollection 在 DataGrid 源上设置了一些数据并将其绑定。我修改了 ObservableCollection 成员属性的值。在这种情况下,我的 UI 必须显示该值已更改。但是,我的 DataGrid 仅在我选择单元格时进行交互。
绑定
public ObservableCollection<MyClass> griddata get; set; = new ObservableCollection<MyClass>();
我的班级
public class MyClass
public int num get; set;
public int idxnumber get; set;
XAML
<Grid>
<DataGrid ItemsSource="Binding griddata, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" >
</DataGrid>
</Grid>
功能
//... griddata.add(someOfData);
public void ViewModel()
int i = 0;
while(i < 30)
testing(0);
i++;
private void testing(int idxnum)
var test = griddata.Where(z => z.idxnumber == idxnum).FirstOrDefalut();
test.num += 1;
结果
单元格值显示0
和我选择的值立即更改为30
。
预期结果
单元格值连续显示0
到30
。
编辑: 这是我的全部代码:
XAML
<Window x:Class="TestSol3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestSol3"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<DataGrid ItemsSource="Binding griddata">
</DataGrid>
</Grid>
</Window>
Model.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestSol3
public class Model
public int num get; set;
public int idxnumber get; set;
ViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestSol3
public class ViewModel
public ObservableCollection<Model> griddata get; set; = new ObservableCollection<Model>();
public ViewModel()
griddata.Add(new Model() num = 0, idxnumber = 0 );
griddata.Add(new Model() num = 1, idxnumber = 1 );
Load(0);
private void Load(int idxnum)
int i = 0;
while(i < 30)
i++;
griddata[idxnum].num++;
//Thread.Sleep(200);
【问题讨论】:
在while (i < 30)
中添加Thread.Sleep(100);
会减慢UI中的值更新速度
@cg-zhou 不工作。我也试过Thread.sleep()
和Task.Delay
,但这并没有帮助。
我尝试按照你的描述构建一个项目,由于缺少部分代码,这似乎很难;如果你提供可运行的 xx.xaml.cs 和 xx.cs,那将有很大帮助。
【参考方案1】:
尝试在你的模型中实现 INotifyPropertyChanged
namespace TestSol3
public class ViewModel : INotifyPropertyChanged
public ObservableCollection<Model> _griddata = new ObservableCollection<Model>();
public ObservableCollection<Model> griddata
get => _griddata;
set
_griddata= value;
OnChangedProperty("griddata");
public void OnChangedProperty(string name)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
【讨论】:
【参考方案2】:[解决方案]
在WPF中,你可以从Application.Current.Dispatcher
得到dispatcher
How to pass the UI Dispatcher to the ViewModel
我们需要更改ObservableCollection
中的项目以通知值更改事件。
ObservableCollection
的文档说:
表示一个动态数据集合,在添加、删除项目或刷新整个列表时提供通知。
https://docs.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.observablecollection-1?view=net-6.0
private void Load(int idxnum)
Task.Run(() =>
int i = 0;
while (i < 30)
i++;
var model = griddata[idxnum];
model.num++;
var dispatcher = Application.Current.Dispatcher;
dispatcher.Invoke(() =>
griddata.RemoveAt(idxnum);
griddata.Insert(idxnum, model);
);
Thread.Sleep(500);
);
[简单演示]
我编写了一个演示项目来展示如何不断更新 UI 值,如下所示。
它使用Task
启动另一个线程来更新UI值,希望对您有所帮助。
MainWindow.xaml
<Window x:Class="TestWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
<StackPanel>
<TextBlock Name="MyTextBlock" FontSize="20"></TextBlock>
<Button Click="Button_Click">Start</Button>
</StackPanel>
</Window>
MainWindow.xaml.cs
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace TestWpfApp
public partial class MainWindow : Window
public MainWindow()
InitializeComponent();
private Task? CurrentTask get; set;
private void Button_Click(object sender, RoutedEventArgs e)
// only one task is supported simultaneously
if (this.CurrentTask != null
&& !this.CurrentTask.IsCompleted)
return;
// start a task to calculate value continuously
this.CurrentTask = Task.Run(() =>
int i = 0;
while (i < 30)
++i;
Thread.Sleep(500);
// update value in the UI thread
this.Dispatcher.Invoke(() =>
this.MyTextBlock.Text = i.ToString();
);
);
【讨论】:
感谢您的回答。我会试试这个。 我发现这个答案最大的问题。很抱歉这个答案,文本块很好用dispatcher
但DataGrid
在属性不断变化时不能很好地工作。
我更新了答案,ObservableCollection
只接受add/remove/refresh
事件。
我找到了这个article以上是关于更改源时DataGrid更新不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Clarity Datagrid-尝试使用克隆对象设置选择不起作用