C# 为“ObservableCollection不更新视图”提供的解决方案不起作用

C# 为“ObservableCollection不更新视图”提供的解决方案不起作用,c#,wpf,C#,Wpf,我有一个数据网格,它绑定到一个名为Programs的ObservableCollection。窗口上有两个按钮,一个用于将选定行中的位字段更改为激活,另一个用于将其更改为停用。由于我们使用的是.EDMX文件,因此无法访问为每个模型类生成的C代码,因此更改程序行中某一行的位字段值不会更改DataGrid中的值。我明白。我向上看了看,我是如何做到这一点的。我发现了一篇大约8年前的帖子,标题是。这看起来很有希望,所以我实现了aqwert给出的解决方案。然而,它仍然不起作用。我知道该值正在被修改,并且按

我有一个数据网格,它绑定到一个名为Programs的ObservableCollection。窗口上有两个按钮,一个用于将选定行中的位字段更改为激活,另一个用于将其更改为停用。由于我们使用的是.EDMX文件,因此无法访问为每个模型类生成的C代码,因此更改程序行中某一行的位字段值不会更改DataGrid中的值。我明白。我向上看了看,我是如何做到这一点的。我发现了一篇大约8年前的帖子,标题是。这看起来很有希望,所以我实现了aqwert给出的解决方案。然而,它仍然不起作用。我知道该值正在被修改,并且按照aqwert的解决方案,我正在替换程序。没关系,它不会更新视图

我们使用的是.NETFramework4.5.2。我们也在使用MVVM灯。我们正在使用FirstFloor软件的ModernUI进行WPF

以下是DataGrid的XAML:

<DataGrid
Grid.Row="3"
Grid.Column="2"
AutoGenerateColumns="False"
BorderThickness="1"
CanUserAddRows="False"
ItemsSource="{Binding Programs}"
SelectedItem="{Binding SelectedProgram, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<DataGrid.Columns>
    <DataGridTemplateColumn
        Width="Auto"
        Header="ID"
        IsReadOnly="True">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding ID}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTemplateColumn
        Width="Auto"
        Header="Abbrev"
        IsReadOnly="True">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding ProgramAbbrev}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTemplateColumn
        Width="Auto"
        Header="Program Name"
        IsReadOnly="True">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding ProgramName}" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTemplateColumn
        Width="Auto"
        Header="Inactive"
        IsReadOnly="True">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Inactive, Converter={StaticResource BoolToYN}}" TextAlignment="Center" />
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>
以下是VM中程序的定义:

private ObservableCollection<Program> programs;
public ObservableCollection<Program> Programs
{
    get { return programs; }
    set
    {
        if (programs != value)
        {
            programs = value;
            RaisePropertyChanged("Programs");
        }
    }
}
最后,这是我根据aqwert的解决方案编写的代码:

//make a copy of Programs
var programsCopy = new List<Program>();
foreach (var item in Programs)
{
    if (item.ID == SelectedProgram.ID)
    {
        item.Inactive = inactiveFlag;
        item.UpdatedBy = Environment.UserDomainName + "\\" + Environment.UserName;
        item.UpdatedOn = rightNow;
    }
    programsCopy.Add(item);
}
//copy over the top of Programs
Programs = new ObservableCollection<Program>(programsCopy);
当集合中单个项的属性被修改时,ObservableCollection不会向UI发出更改通知。方法是在程序类中实现INotifyPropertyChanged事件

如果出于任何原因无法修改程序,可以创建一个新的视图模型类,并将源集合属性的类型从ObservableCollection更改为IEnumerable。如果每次要更改集合时都将Programs属性重置为新实例,则不需要ObservableCollection


然后在ProgramViewModel类中实现INotifyPropertyChanged并绑定到此类的属性。

我终于发现了我的问题。我犯了愚蠢的错误。我有两个例程,每个例程绑定到两个不同的ICommand。一个用于激活按钮,另一个用于停用按钮。我只想停用按钮的代码:

private void ExecuteDeActivateCommand()
{
    SetInactiveFlag(true);
    GetProgramsSynchronously(SelectedRow.ID); //this call was what was causing me problems
}
昨天我向您展示了SetInactiveFlagtrue调用中的一些代码。这工作正常,正在将非活动位标志设置为true。但是,我忘了调用GetProgramsSynchronouslySelectedRow.ID调用会违反数据库并刷新内存中的程序集合,而Inactive标志设置为false


鸡蛋在我脸上。我希望你们都能从我的错误中吸取教训,希望你们能避免脸上挂着鸡蛋。

如果你们只创建一个新的程序集合并进行复制,就根本不需要使用ObservableCollection。我们所做的不仅仅是复制。用户还可以向可观察集合添加其他行。按照规范,一旦用户选择了要添加的新程序,它就会添加到数据库中,然后我从数据库中刷新程序集合。在这种情况下,当用户希望将程序从活动或停用状态更改为活动或停用状态时,则只能在内存中执行,而不能在数据库中执行,根据规范。根据规范,所有此类修改都要求用户单击“保存”按钮以保留这些更改。由于您无权访问包含位字段属性的模型类,因此无法验证它是否实现了iNotifyPropertyChanged。ObservableCollection可以处理新集合项的通知,但不能处理集合中某个项内的单个属性。我猜您绑定的属性也没有实现iNotifyPropertyChanged,在这种情况下,它将永远不会通知您的DataGrid进行更新。如果是这种情况,您可能需要手动刷新绑定。正如Tronald提到的,observablecollection只会在整个集合发生更改时发出通知。如果集合中元素的某些属性已更改,则不会更改。。有很多图书馆可以提供帮助。我已经为这些任务创建了轻量级MVVM库。试着用这个。我有一个名为FlipperObservableCollection的集合,它可以在属性更改时触发。它位于名称空间Haley.Flipper.MVVM.ModelsThank you、Tronald和Lingam中。我明天上班的时候试试。