ItemsSource更改时,DataGrid不会更新

时间:2016-07-29 17:48:33

标签: c# wpf data-binding

我有一个AccountManager的课程Singleton class,实现为namespace SampleApp.Manager { public class AccountManager : INotifyCollectionChanged, INotifyPropertyChanged { public static AccountManager Instance { get; } = new AccountManager(); public event NotifyCollectionChangedEventHandler CollectionChanged; public event PropertyChangedEventHandler PropertyChanged; private List<Account> InternalAccounts { get; } = new List<Account>(); public IReadOnlyCollection<Account> Accounts => InternalAccounts; private AccountManager() { } public void Add(Account account) { InternalAccounts.Add(account); CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, account)); OnPropertyChanged(nameof(Accounts)); } public void Remove(Account account) { if (InternalAccounts.Remove(account)) { CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, account)); OnPropertyChanged(nameof(Accounts)); } } protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }

Page

然后我有Account我希望使用这些<Page x:Class="SampleApp.View.AccountView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mgr="clr-namespace:SampleApp.Manager" mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="800" Title="AccountView"> <Grid> <TextBlock Text="{Binding Source={x:Static mgr:AccountManager.Instance}, Path=Accounts.Count}" /> <DataGrid ItemsSource="{Binding Source={x:Static mgr:AccountManager.Instance}, Path=Accounts}"> <DataGrid.Columns> <DataGridTextColumn Header="Property1" Binding="{Binding Property1, Mode=TwoWay}" Width="*" /> <DataGridTextColumn Header="Property2" Binding="{Binding Property2, Mode=TwoWay}" Width="*" /> <DataGridTextColumn Header="Property3" Binding="{Binding Property3, Mode=TwoWay}" Width="*" /> <DataGridTextColumn Header="Property4" Binding="{Binding Property4, Mode=TwoWay}" Width="*" /> </DataGrid.Columns> </DataGrid> </Grid> </Page> 个实例:

AccountManager.CollectionChanged

我首先尝试仅触发DataGrid更新视图中的INotifyPropertyChanged,但这没有做任何事情。接下来我实施了AccountManager.PropertyChanged并触发了TextBlock,但没有更新列表,只有AccountManager.Accounts包含ObservableCollection<T>中当前的项目数。

这只是类实际外观的简化版本,这就是为什么我不使用ObservableCollection<T>来执行此操作的原因,所以请不要责怪我不使用{{1} }。

我想知道我的代码有什么问题?我不明白为什么DataGrid绑定没有得到更新,但TextBlock会更新。

1 个答案:

答案 0 :(得分:0)

InternalAccountsList,而不是ObservableCollection。你永远不会告诉任何人你的名单改变了。在拥有它的viewmodel上实施INotifyCollectionChanged并不能帮助List引发任何事件:当List发生更改时,您会引发事件,说明您的viewmodel 拥有< / em>项目已更改,但实际上并没有任何项目 - 其项目位于列表中,这是XAML绑定的内容。

如果您使InternalAccounts成为ObservableCollection并制作Accounts ReadOnlyObservableCollection,那么应该修复它。

private OnlyObservableCollection<Account> _accounts = 
    new OnlyObservableCollection<Account>();

private ReadOnlyObservableCollection<Account> _roAccounts;
public ReadOnlyObservableCollection<Account> Accounts
{
    get { 
        if (_roAccounts == null)
            _roAccounts = new ReadOnlyObservableCollection<Account>(_accounts);
        return _roAccounts;
    }
}

在内部,只需添加和删除_accounts中的内容,而不必在您的视图模型上实施INotifyCollectionChanged。您只需免费获得完整的实施,即开即用。这比你想象的要容易得多,总是很好。