簡體   English   中英

ItemsSource更改時,DataGrid不更新

[英]DataGrid not updating when ItemsSource changes

我有一個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));
        }
    }
}

然后,在我要使用這些Account實例的地方有Page

<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但是它沒有更新列表,而是僅更新了包含AccountManager.Accounts當前項目數的TextBlock

這只是類實際外觀的簡化版本,這就是為什么我不使用ObservableCollection<T>來執行此操作的原因,所以請不要怪我不使用ObservableCollection<T>

我想知道我的代碼有什么問題嗎? 我不明白為什么DataGrid綁定沒有得到更新,但是TextBlock得到了更新。

InternalAccounts是一個List ,而不是ObservableCollection 您永遠不會告訴任何人您的列表已更改。 在擁有它的視圖INotifyCollectionChanged上實現INotifyCollectionChanged並不能幫助List引發任何事件:當List發生更改時,您確實引發了一些事件,表明您的ViewModel 自己的項目已更改,但實際上沒有任何項目-它的項目位於列表,這是XAML綁定到的列表。

如果將InternalAccountsObservableCollection並將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上實現INotifyCollectionChanged 您剛剛獲得了免費的完整實現,即可使用。 這比您想象的要容易得多,這總是很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM