DataGrid将不会刷新

时间:2019-08-17 00:51:07

标签: c# uwp datagrid

我有一个DataGrid,它使用ObservableCollection作为ItemsSource。

集合中的项目是自定义类的项目。

当我编辑其中一项时,无论执行什么操作都无法更新视图。我尝试删除所有项目并将其重新添加到集合中,并且尝试将集合重新分配到网格中。

我知道所做的修改已正确保存,因为我可以在调试器中看到更改的值。

什么可能导致这种情况发生?

还有其他方法可以强制网格刷新吗?

1 个答案:

答案 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,但是不建议这样做,因为该项目将附加到集合的末尾,因此需要使用自定义排序逻辑,至少可以说