【问题标题】:Datagrid not updating after data change数据更改后Datagrid不更新
【发布时间】:2014-01-23 03:07:59
【问题描述】:

我有一个 WPF DataGrid 通过 dg.ItemsSource = myCollection; 绑定到 ObservableCollection

MyClass 实现了INotifyPropertyChanged。我有一个计算出来的属性,它是异步计算的。

该属性是绑定到文本颜色的 SolidColorBrush。属性值更改后,DataGrid 不会立即更新,但只要我选择属性更改的项目的行,它就会立即更新,它会显示更新后的值。

如何让 DataGrid 立即更新?我不能对 ItemsSource 使用 XAML 绑定。

绑定:

<DataGridTextColumn Foreground={Binding Path=MyBrushProperty} />

类代码:

public class MyClass : INotifyPropertyChanged
{
public SolidColorBrush MyBrushProperty {
   get {
      CalcMyBrush();
      return _myBrushProperty;
   }
  set{
   _myBrushProperty = value; 
   OnPropertyChanged("MyBrushProperty");
  }
}
private void CalcMyBrush(){
   //DoSomething that changes _myBrushProperty and takes some time and needs to run async and after that sets
   MyBrushProperty = somevalue;

}
}

【问题讨论】:

  • 在此处发布相关的 XAML 代码。
  • @RohitVats 基本上是 Foreground={Binding Path=MyColorProperty}
  • 如果异步评估,请尝试在绑定中指定异步。 Foreground={Binding Path=MyColorProperty,IsAsync=True}.
  • I can't use XAML binding in this case - 什么?
  • @HighCore 添加了虚拟代码并解释了

标签: c# wpf datagrid


【解决方案1】:

我认为在获得异步计算结果后,您需要为计算的属性触发 PropertyChanged 事件。

类似的东西

public SolidColorBrush MyBrushProperty{get{return myBrushProperty;}}
private void CalcMyBrush()
{
    var awaiter = YourAsyncCalculation.GetAwaiter();
    awaiter.OnComplited(()=>
    {
     myBrushProperty= (SolidColorBrush)awaiter.GetResult();
     OnPropertyChanged("MyBrushProperty"); 
    });
}

【讨论】:

  • 我因为另一个建议而改变了它。但我确保在值更改后调用 PropertyChanged 事件。仍然没有效果。我认为问题出在某个地方,当 DataGrid 决定更新时。
  • 当您启动网格时,请执行属性 get{} 逻辑并调用异步方法,它可能不会等待结果;所以我最好在传入参数发生变化时初始化计算并使属性的读取变得容易
  • 在 WPF DataGrid 中旨在仅在 PropertyChangend 事件上更新值。它不需要像 Winforms 中的其他东西。如果您需要更新整个集合,则需要在 ViewModel 的集合属性上触发 PropertyChanged 事件
【解决方案2】:

请注意,您无法从不同的线程更改 UI 项目(请参阅 STA Apartment State)。这个想法是创建线程是创建项目的单一所有者。 例如,以下代码不好,原因有两个: 1. NotifyOfPropertyChange("MyBrushProperty");可能在计算任务之前调用。 2.不太明显,任务内容会导致异常说:

调用线程无法访问此对象,因为另一个线程拥有它。 这里可能存在一些问题。

确保打开所有异常标志或探索 _myBrushProperty 中的颜色属性

    public class ModuleBMainWindowViewModel : Screen , INotifyPropertyChanged
{
    public ModuleBMainWindowViewModel()
    {
        _myBrushProperty = new SolidColorBrush(Colors.White);
        DisplayName = "ModuleB";
        CalcMyBrush();

    }
    private SolidColorBrush _myBrushProperty;
    public SolidColorBrush MyBrushProperty
    {
        get
        {
            return _myBrushProperty;
        }
        set
        {
            _myBrushProperty = value;
        }
    }
    private void CalcMyBrush()
    {
         Task.Run(() =>
        {
            //DoSomething that changes _myBrushProperty and takes some time and needs to run async and after that sets
            _myBrushProperty = new SolidColorBrush(Colors.Blue);
        });

         NotifyOfPropertyChange("MyBrushProperty");
    }
}

【讨论】:

  • 这应该是一条评论。
  • 我还没有适当的评论声望,但 10 倍的提醒;
  • OP 已经提到了问题 - The class the ObservableCollection contains implements INotifyPropertyChanged.
  • @MichaelLo 我正在使用 INotifyPropertyChanged。该行正在更新,但正如我选择它而不是值真正改变时一样。
  • 尝试从 CalcMyBrush() 中获取 OnPropertyChanged("MyBrushProperty") 代码并将其放在“get { .. }”中
猜你喜欢
  • 2014-08-17
  • 1970-01-01
  • 1970-01-01
  • 2018-11-29
  • 2021-11-04
  • 1970-01-01
  • 2011-12-16
  • 2012-02-23
  • 1970-01-01
相关资源
最近更新 更多