我在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开始追加到列表视图的末尾。
编辑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;
答案 0 :(得分:2)
由于您未添加任何删除项目,并且您要更换引用,因此您需要引发事件,告知视图已更改。而不是你的代码,用这个
替换它 private ObservableCollection<Standing> _leagueStandings;
public ObservableCollection<Standing> LeagueStandings
{
get { return _leagueStandings; }
set {
_leagueStandings = value;
RaisePropertyChanged("LeagueStandings");
}
}
另外,对于将来的推荐,ObservableCollection
已经实施INotifyPropertyChanged
,因此您不需要SetValue(x)
..