【问题标题】:WPF DataGrid.ItemSourceWPF DataGrid.ItemSsource
【发布时间】:2009-06-11 16:00:25
【问题描述】:

我通过 DataGrid.ItemSource 属性将 IEnumerable Collection 传递到 WPF DataGrid 中。但是当我尝试更改代码中的集合项时,它不会更新 DataGrid。 为什么?

【问题讨论】:

    标签: wpf datagrid datagridview


    【解决方案1】:

    您需要绑定到实现 INotifyCollectionChanged 接口的类型,以便它提供数据绑定可用于监控何时添加或删除项目的事件。 WPF 中最好的类型是 ObservableCollection,它有一个可以接受 IEnumerable 的构造函数:

    ObservableCollection<string> collection = new ObservableCollection<string>(iEnumerableobject);
    dataGrid.ItemSource = collection;
    collection.Add("Wibble");
    

    会正确更新。


    从您的 cmets 到另一个答案,您似乎需要从 UI 线程内部调用 add 调用。在不详细了解您的代码的情况下,我不知道您为什么需要这样做,但我们假设您正在后台从服务获取数据:

    private ObservableCollection<string> collection;
    
    public void SetupBindings()
    {
        collection = new ObservableCollection<string>(iEnumerableobject);
        dataGrid.ItemSource = collection;
        //off the top of my head, so I may have this line wrong
        ThreadPool.Queue(new ThreadWorkerItem(GetDataFromService));
    }
    
    public void GetDataFromService(object o)
    {
         string newValue = _service.GetData();
    
         //if you try a call add here you will throw an exception
         //because you are not in the same thread that created the control
         //collection.Add(newValue);
    
         //instead you need to invoke on the Ui dispatcher
         if(Dispather.CurrentDispatcher.Thread != Thread.CurrentThread)
         { 
             Dispatcher.CurrentDispatcher.Invoke(() => AddValue(newValue));
         } 
    }
    
    public void AddValue(string value)
    {
        //because this method was called through the dispatcher we can now add the item
        collection.Add(value);
    }
    

    正如我所说,我手头没有 IDE,所以这可能无法编译,但会为您指明正确的方向。

    不过,根据您在后台执行的具体任务,可能会有更好的方法来执行此操作。我上面的例子使用backgroundworker 会更容易实现,所以你可能也想了解一下。

    【讨论】:

    • 为那个人+1,而不仅仅是在答案中使用“Wibble”。干得好我说! . . .是的,今天下午我感觉有点奇怪。 . .
    • 我改成了 ObservableCollection,但还是没有什么区别。当我第一次启动程序时它会显示正确的数据,但之后就不会更新 Grid ......我做错了什么
    【解决方案2】:

    您需要改用 ObservableCollection。 (或者让你自己的类包装集合并实现 INotifyPropertyChanged 接口)

    【讨论】:

    • 当我试图对集合进行更改时,VS 说:这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。
    • 当集合绑定到 GUI 时,您只能从主 GUI 线程对集合进行更改。您可以通过在表单调度程序上调用 Invoke 来完成此操作。执行 if(Dispather.CurrentDispatcher.Thread != Thread.CurrentThread){ 然后调用 Dispatcher.CurrentDispatcher.Invoke(并将委托传递给您的方法)参见此处:msdn.microsoft.com/en-us/library/…
    • 您需要在 UI 线程上进行所有更新,因为 WPF 仅支持从创建控件的线程修改控件。
    【解决方案3】:

    如果由于某种原因不能使用 ObservableCollection,也可以使用实现 INotifyCollectionChanged 接口的集合...

    【讨论】:

      猜你喜欢
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多