我有一个DataGrid,它使用ObservableCollection作为ItemsSource。
集合中的项目是自定义类的项目。
当我编辑其中一项时,无论执行什么操作都无法更新视图。我尝试删除所有项目并将其重新添加到集合中,并且尝试将集合重新分配到网格中。
我知道所做的修改已正确保存,因为我可以在调试器中看到更改的值。
什么可能导致这种情况发生?
还有其他方法可以强制网格刷新吗?
答案 0 :(得分:0)
如ObservableCollection文档中所述,在集合中仅通知插入和删除操作,该集合由CollectionChanged事件公开。为了使ObservableCollection
中的项目已进行更改,底层模型必须实现INotifyPropertyChanged:
帐户:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TestUWP
{
public class Account : INotifyPropertyChanged
{
private string _accountName;
private decimal _amount;
public string AccountName
{
get => _accountName;
set
{
_accountName = value;
OnPropertyChanged();
}
}
public decimal Amount
{
get => _amount;
set
{
_amount = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
ViewModel + RelayCommand:
using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace TestUWP
{
public class AccountViewModel
{
public AccountViewModel()
{
Accounts = new ObservableCollection<Account>
{
new Account {AccountName = "Account 1", Amount = 1000M},
new Account {AccountName = "Account 2", Amount = 2000M},
new Account {AccountName = "Account 3", Amount = 3000M},
};
AddAccountCommand = new RelayCommand(AddAccount);
EditAccountCommand = new RelayCommand(EditAccount);
}
public ICommand AddAccountCommand { get; }
public ICommand EditAccountCommand { get; }
public ObservableCollection<Account> Accounts { get; }
private void AddAccount()
{
Accounts.Add(new Account{AccountName = $"Account {Accounts.Count+1}", Amount = 1000M * (Accounts.Count+1)});
}
private void EditAccount()
{
Accounts[Accounts.Count - 1].Amount += 200M;
}
}
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action execute, Func<bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute?.Invoke() ?? true;
public void Execute(object parameter) => _execute();
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
主页:
<Page
x:Class="TestUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.DataContext>
<local:AccountViewModel />
</Page.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ListView Grid.Column="0" Grid.RowSpan="2" ItemsSource="{Binding Accounts}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding AccountName}" Grid.Column="0" FontSize="30"/>
<TextBlock Text="{Binding Amount}" Grid.Column="1" Margin="30,0,0,0" FontSize="30"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Grid.Column="1" Grid.Row="0" Content="Add" FontSize="50" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Command="{Binding AddAccountCommand}"/>
<Button Grid.Column="1" Grid.Row="1" Content="Edit" FontSize="50" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Command="{Binding EditAccountCommand}"/>
</Grid>
</Page>
将帐户从POCO更改为实施INotifyPropertyChanged
的帐户后,只要单击“编辑”按钮,UI即可刷新金额。
或者,删除和重新插入项目也会更新ItemSource
,但是不建议这样做,因为该项目将附加到集合的末尾,因此需要使用自定义排序逻辑,至少可以说