C# 如何根据 WPF DataGrid 中的更改更新 ObservableCollection 项的属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9984274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:00:32  来源:igfitidea点击:

How do I update an ObservableCollection item's property from change in a WPF DataGrid?

c#wpfbindingwpfdatagridobservablecollection

提问by K J

I have a WPF DataGrid who's data source is an ObservableCollection. It is set up loosely as the following:

我有一个 WPF DataGrid,它的数据源是 ObservableCollection。它的设置松散如下:

public class ItemDataCollection : ObservableCollection<ItemData>
{
}

public class ItemData : INotifyPropertyChanged
{
    private bool _selected = true;
    public bool Selected 
    { 
        get
        {
            return _selected;
        }
        set
        {
            if (value != _selected)
            {
                _selected = value;
                NotifyPropertyChanged("Selected");
            }
        }
    }
    }


    _itemDataCol = new ItemDataCollection();
        <... fill the _itemDataCol with data here ...>
    dataGrid1.ItemsSource = _itemDataCol;

When the collection is updated, a dataGrid1.Items.Refresh() updates dataGrid1 nicely. However when I modify the "Selected" property of a row by checking or unchecking the checkbox in the row corresponding to that property, the item in the collection does not get updated. I looked into the CollectionChanged event of the ObeservableCollection, but that is not appearing to get triggerd. What wiring do I need to get the dataGrid1 to update the collection.

更新集合时,dataGrid1.Items.Refresh() 会很好地更新 dataGrid1。但是,当我通过选中或取消选中与该属性对应的行中的复选框来修改行的“Selected”属性时,集合中的项目不会更新。我查看了 ObeservableCollection 的 CollectionChanged 事件,但这似乎没有被触发。我需要什么接线才能让 dataGrid1 更新集合。

Update

更新

All I was doing was setting the ItemSource property to the ObservableCollection and letting the columns auto-generate. I have since changed to bind directly, and found more detail to the problem. When I simply check the box - no notification is triggerd. However if I hit after checking the box, then the collection is updated. Here is the binding:

我所做的只是将 ItemSource 属性设置为 ObservableCollection 并让列自动生成。此后我更改为直接绑定,并找到了问题的更多详细信息。当我简单地选中该框时 - 不会触发任何通知。但是,如果我在选中该框后点击,则该集合会更新。这是绑定:

<DataGridCheckBoxColumn Binding="{Binding Path=Selected, Mode=TwoWay}" Header="Selected"></DataGridCheckBoxColumn>

So I guess the question is how do I get the update with having to hit after checking or unchecking the box?

所以我想问题是如何在选中或取消选中该框后必须点击才能获得更新?

Update #2(I cannot answer as my rep is not high enough yet) OK - I think I have the solution. If I include "UpdateSourceTrigger=PropertyChanged" in the binding everything seems to work.

更新 #2(我无法回答,因为我的代表还不够高)好的 - 我想我有解决方案。如果我在绑定中包含“UpdateSourceTrigger=PropertyChanged”,一切似乎都正常。

<DataGridCheckBoxColumn Binding="{Binding Path=Selected, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Header="Selected"></DataGridCheckBoxColumn>

Please leave comments if there are any negative affects of this that I may be missing. Thanks for the help!

如果对此有任何我可能遗漏的负面影响,请发表评论。谢谢您的帮助!

采纳答案by paparazzo

CollectionChanged is for Insert and Delete. NotifyPropertyChanged is for update of an items. In the posted code you don't actually implement INotifyPropertyChanged.

CollectionChanged 用于插入和删除。NotifyPropertyChanged 用于更新项目。在发布的代码中,您实际上并未实现 INotifyPropertyChanged。

   public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

And I think it is cleaner to bind to a public property where you return _itemDataCol

而且我认为绑定到返回 _itemDataCol 的公共属性更干净

Otherwise the TwoWay answer of celopez3

否则 celopez3 的 TwoWay 答案

回答by celopez3

I'm not sure that you have put enough information in your post, but I will try to help. One of my first question is: how are you binding to the check box? It must be noted that if you want the check box to affect the observable collection you must institute a "two-way" bind on the item, by default the bind is "one-way" and will not automatically change the item in your collection. Another way to handle this would be to add an event on the check box that when clicked you would manually change the value in the observable collection.

我不确定您在帖子中是否提供了足够的信息,但我会尽力提供帮助。我的第一个问题是:您如何绑定到复选框?必须注意的是,如果您希望复选框影响 observable 集合,则必须对该项目进行“双向”绑定,默认情况下绑定是“单向”并且不会自动更改集合中的项目. 处理此问题的另一种方法是在复选框上添加一个事件,单击该事件时您将手动更改 observable 集合中的值。

回答by Aphex

An ObservableCollectiondoesn't listen to its items' INotifyPropertyChangedevents; use a BindingListinstead.

AnObservableCollection不监听其项目的INotifyPropertyChanged事件;使用 aBindingList代替。

In other words, [an ObservableCollection] only notices when items are added or removed, not when the values of its items change, even if those items implement INotifyPropertyChanged. In comparison, a BindingList DOES listen to INotifyPropertyChanged, and therefore, if its items are modified, the changes will be reflected in the grid. As a result grouping, sorting, and statistical functions will be updated.

换句话说, [an ObservableCollection] 仅在添加或删除项目时通知,而不在其项目的值更改时通知,即使这些项目实现了 INotifyPropertyChanged。相比之下,BindingList 确实会侦听 INotifyPropertyChanged,因此,如果修改其项目,则更改将反映在网格中。因此,将更新分组、排序和统计功能。

http://xceed.com/CS/blogs/dontpanic/archive/2009/04/01/i-notify-we-notify-we-all-wait-no-we-don-t.aspx

http://xceed.com/CS/blogs/dontpanic/archive/2009/04/01/i-notify-we-notify-we-all-wait-no-we-don-t.aspx

回答by K J

The answer is that I needed to set the UpdateSourceTrigger to PropertyChanged (see Blam's response). Two-way binding did not seem to need to be specified. Here is the markup from the working code:

答案是我需要将 UpdateSourceTrigger 设置为 PropertyChanged(参见 Blam 的响应)。似乎不需要指定双向绑定。这是工作代码中的标记:

<DataGridCheckBoxColumn Binding="{Binding Path=Selected,
     UpdateSourceTrigger=PropertyChanged}" 
     Header="Selected"></DataGridCheckBoxColumn>