DataGrid 中未表示的 ObservableCollection<T> 的异步修改
Async modification of ObservableCollection<T> not represented in DataGrid
我已经有一段时间没和 Forms/WPF 一起工作了。如果这是一个愚蠢的问题,请原谅。
我有一个名为 myObservable
的 ObservableCollection<myClass>
,其中 myClass
包含以下内容:
public class myClass
{
public string myStringOne { get; set; }
public string myStringTwo { get; set; }
public string myStringThree { get; set; }
public string mystringFour { get; set; }
}
并在UI.xaml下面进行控制。
<Grid HorizontalAlignment="Left" Height="239" VerticalAlignment="Top" Width="439">
<DataGrid x:Name="PhoneGrid" VerticalAlignment="Top" Height="134"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
CanUserSortColumns="False"
Focusable="False"
IsReadOnly="True"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
ItemsSource="{Binding myObservable}" MouseLeftButtonUp="PhoneGrid_MouseLeftButtonUp" SelectionUnit="Cell" Margin="10,100,10,0" />
我设置 backgroundworker 的方式:
private readonly BackgroundWorker _worker = new BackgroundWorker();
private readonly object _lock = new object();
_worker.DoWork += LoadLines;
var timer = new Timer(Settings.Default.Interval);
timer.Elapsed += timer_Elapsed;
timer.Start();
LoadLines
是我执行 UI 阻止事情的功能。
我尝试实现
// Prepare obervable collection
BindingOperations.EnableCollectionSynchronization(myObservable, _lock);
以及
Dispatcher.Invoke(() => {
myObservable[index].myString = "anyStr";
});
当我从 myObservable
中添加和删除 myClass
' 时它起作用了。但是,当我更改 myClass
的 属性 时,即使 myObservable
的值已更改,更改也不会反映在 WPF DataGrid 中。
我错过了什么?
我尝试了其他几个来源,但无济于事。奇怪的是,在 UI 线程以外的线程上修改集合似乎是可能的。当 运行 在新线程上或在 UI 线程上调用它时,我无法察觉任何行为差异。
您的 myClass 需要实现 INotifyPropertyChanged。这就是 WPF 数据绑定通知 UI 属性更改的方式。
public class myClass: INotifyPropertyChanged
{
private string _myStringOne;
public string myStringOne {
get { return _myStringOne; }
set
{
if(_myStringOne != value)
{
_myStringOne = value;
NotifyPropertyChanged("myStringOne");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
我已经有一段时间没和 Forms/WPF 一起工作了。如果这是一个愚蠢的问题,请原谅。
我有一个名为 myObservable
的 ObservableCollection<myClass>
,其中 myClass
包含以下内容:
public class myClass
{
public string myStringOne { get; set; }
public string myStringTwo { get; set; }
public string myStringThree { get; set; }
public string mystringFour { get; set; }
}
并在UI.xaml下面进行控制。
<Grid HorizontalAlignment="Left" Height="239" VerticalAlignment="Top" Width="439">
<DataGrid x:Name="PhoneGrid" VerticalAlignment="Top" Height="134"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
CanUserSortColumns="False"
Focusable="False"
IsReadOnly="True"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}"
ItemsSource="{Binding myObservable}" MouseLeftButtonUp="PhoneGrid_MouseLeftButtonUp" SelectionUnit="Cell" Margin="10,100,10,0" />
我设置 backgroundworker 的方式:
private readonly BackgroundWorker _worker = new BackgroundWorker();
private readonly object _lock = new object();
_worker.DoWork += LoadLines;
var timer = new Timer(Settings.Default.Interval);
timer.Elapsed += timer_Elapsed;
timer.Start();
LoadLines
是我执行 UI 阻止事情的功能。
我尝试实现
// Prepare obervable collection
BindingOperations.EnableCollectionSynchronization(myObservable, _lock);
以及
Dispatcher.Invoke(() => {
myObservable[index].myString = "anyStr";
});
当我从 myObservable
中添加和删除 myClass
' 时它起作用了。但是,当我更改 myClass
的 属性 时,即使 myObservable
的值已更改,更改也不会反映在 WPF DataGrid 中。
我错过了什么?
我尝试了其他几个来源,但无济于事。奇怪的是,在 UI 线程以外的线程上修改集合似乎是可能的。当 运行 在新线程上或在 UI 线程上调用它时,我无法察觉任何行为差异。
您的 myClass 需要实现 INotifyPropertyChanged。这就是 WPF 数据绑定通知 UI 属性更改的方式。
public class myClass: INotifyPropertyChanged
{
private string _myStringOne;
public string myStringOne {
get { return _myStringOne; }
set
{
if(_myStringOne != value)
{
_myStringOne = value;
NotifyPropertyChanged("myStringOne");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}