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