我有一个绑定到名为Programs的ObservableCollection的DataGrid。在窗口上有2个按钮,一个用于将所选行中的位字段更改为激活,另一个用于将其更改为停用。由于我们使用的是.EDMX文件,因此无权访问每个模型类生成的C#代码,因此更改“程序”行之一中的位字段的值不会更改DataGrid中的值。我明白那个。我在这里查找了如何执行此操作。我发现了将近8年前的一则帖子,名为ObservableCollection not updating View。这看起来很有希望,所以我实施了aqwert提供的解决方案。但是,它仍然无法正常工作。我知道值正在被修改,按照aqwert的解决方案,我要替换程序。没关系,它不会更新视图。
我们正在使用.NET Framework 4.5.2。我们也在使用MVVM Light。而且我们正在使用FirstFloor Software的ModernUI for 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);
答案 0 :(得分:1)
修改集合中各个项目的属性时,ObservableCollection<T>
不会向UI发出更改通知。实现此目的的方法是在INotifyPropertyChanged
类中实现Program
事件。
如果由于某种原因无法修改Program
,则可以创建一个wraps的新视图模型类,并将源集合属性的类型从ObservableCollection<Programs>
更改为{ {1}}。如果每次要更改集合时都将IEnumerable<ProgramViewModel>
属性重置为新实例,则不需要ObservableCollection
。
然后您在Programs
类中实现INotifyPropertyChanged
并绑定到该属性。
答案 1 :(得分:0)
我终于发现了我的问题。我这是愚蠢的错误。我有2个例程,每个例程绑定到两个不同的ICommands。一个用于“激活”按钮,另一个用于“停用”按钮。我只需要停用按钮的代码即可:
for ($i = 0; $i < $count; $i++) {
$participant = new Participant();
$participant->p_name = $participantArray[0][$i]['name'];
$participant->p_email = $participantArray[0][$i]['email'];
$participant->p_address = $participantArray[0][$i]['address'];
$participant->p_postcode = $participantArray[0][$i]['postcode'];
$participant->p_city = $participantArray[0][$i]['city'];
$participant->p_state = $participantArray[0][$i]['state'];
$participant->p_contact = $participantArray[0][$i]['contactno'];
$confirmation_code = str_random(30);
$participant->confirmation_code = $confirmation_code;
$participant->save();
$participant->campaign()->attach($request->campaign_id);
$details = [
'email' => $participantArray[0][$i]['email'],
'confirmation_code' => $confirmation_code
];
$emailJob = (new SendEmail($details))->delay(Carbon::now()->addSeconds(10));
dispatch($emailJob);
}
昨天我向您展示了SetInactiveFlag(true)调用中的一些代码。效果很好,并将Inactive位标志设置为true。但是,我忘记了调用GetProgramsSynchronously(SelectedRow.ID)调用会针对数据库并刷新内存中的Programs集合,并且Inactive标志设置为false。
鸡蛋在我的脸上。我希望大家都从我的错误中吸取教训,因此希望您避免在自己的脸上生鸡蛋。