更新ObservableCollection无法正确更新Xamarin Forms中的ListView

时间:2018-03-06 17:54:43

标签: c# listview xamarin xamarin.forms observablecollection

我在XAML中有一个ListView,它绑定到ViewModel中的ObservableCollection。在初始化或OnAppearing()时,ListView项目将完美显示。

但是,当我尝试从页面内部(通过ViewModel)更新ListView项目时,项目会更新,但旧项目仍然存在。

基本上,新项目会添加到ListView,但会在之前的ObservableCollection项目下面。我已经实现了INotifyPropertyChanged,我认为我已经做了一切正确的事情(虽然显然没有)。

请告诉我我做错了什么。我在集合上尝试过Clear()但没有用(同样的结果)。

BaseViewModel:

public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        protected void SetValue<T>(ref T backingField, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(backingField, value))
                return;

            backingField = value;

            OnPropertyChanged(propertyName);
        }
}

XAML:

<ListView       IsEnabled="{Binding IsLoadingTable, Converter={Helpers:InverseBoolConverter}}"
                        IsVisible="{Binding IsLoadingTable, Converter={Helpers:InverseBoolConverter}}"
                        ItemsSource="{Binding LeagueStandings}"
                        SelectedItem="{Binding SelectedTeam, Mode=TwoWay}"
                        ItemSelected="ListView_ItemSelected"
                        RowHeight="60"
                        SeparatorVisibility="Default"
                        SeparatorColor="{DynamicResource accentColor}">

Page.cs:

protected override void OnAppearing()
        {
            base.OnAppearing();

            ViewModel.LoadLeagueStandingsCommand.Execute(_divisionId);
            ViewModel.LoadPickerItemsCommand.Execute(null);
        }

ViewModel初始化:

private ObservableCollection<Standing> _leagueStandings;
        public ObservableCollection<Standing> LeagueStandings
        {
            get { return _leagueStandings ?? (_leagueStandings = new ObservableCollection<Standing>()); }
            set { SetValue(ref _leagueStandings, value); }
        }

ViewModel方法:

private async Task LoadLeagueStandings(string divId)
        {

            if (_hasLoadedStandings)
                return;

            if (IsLoadingTable)
                return;

            _hasLoadedStandings = true;

            _divisionId = divId;

            try
            {
                IsLoadingTable = true;
                await _pageService.DisplayAlert("loading Selected", _divisionId, "ok");
                var v = await GetLeagueTableAsync(_htmlParser, _divisionId);

                LeagueStandings = new ObservableCollection<Standing>(v);

            }
            catch (Exception)
            {
                System.Diagnostics.Debug.WriteLine("Exception caught in DivisionsViewModel.cs.(LoadLeagueStandings).");
            }
            finally
            {
                IsLoadingTable = false;
            }

        }

Picker项目更改时调用的ViewModel方法:

private async Task SelectItem(string item)
        {
            if (item == null)
                return;

            SelectedItem = null;

            var id = await _divisionFinder.GetDivisionIdAsync(item);

            var v = await GetLeagueTableAsync(_htmlParser, id);

            LeagueStandings = new ObservableCollection<Standing>(v);
        }

编辑* - 结果的图片。第一个集合以5号结尾,新集合再次从1开始追加到列表视图的末尾。

ListView Image

编辑2:

public async Task<IEnumerable<Standing>> GetLeagueTableAsync(string divisionId)
    {
        // todo: get division Id from picker

        string address = "";
        if (IsOnline)
        {
            if (divisionId != "")
                address = $"{BaseUrls.LeagueStandings}{divisionId}";

            try
            {
                var config = Configuration.Default.WithDefaultLoader();
                var document = await BrowsingContext.New(config).OpenAsync(address);
                var cSelector = "table[class='table table-striped table-hover table-bordered'] tr";

                var table = document.QuerySelectorAll(cSelector).Skip(1);

                int count = 0;
                foreach (var c in table)
                {
                    var cells = c.QuerySelectorAll("td").ToArray();

                    _leagueStandings.Add(new Standing(++count, cells[0].TextContent.Trim(), cells[1].TextContent.Trim(),
                                                               cells[2].TextContent.Trim(), cells[3].TextContent.Trim(),
                                                               cells[4].TextContent.Trim(), cells[5].TextContent.Trim(),
                                                               cells[6].TextContent.Trim(), cells[7].TextContent.Trim()));
                }
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine($"\n\n Exception caught LoadingLeagueTable - {e} \n\n");
            }
        }
        return _leagueStandings;

1 个答案:

答案 0 :(得分:2)

由于您未添加任何删除项目,并且您要更换引用,因此您需要引发事件,告知视图已更改。而不是你的代码,用这个

替换它
    private ObservableCollection<Standing> _leagueStandings;
    public ObservableCollection<Standing> LeagueStandings
    {
        get { return _leagueStandings; }
        set { 
              _leagueStandings = value;
              RaisePropertyChanged("LeagueStandings"); 
            }
    }

另外,对于将来的推荐,ObservableCollection已经实施INotifyPropertyChanged,因此您不需要SetValue(x) ..