[英]Xamarin Forms ListView not updating without navigating to new page
所以我正在使用Xamarin Forms創建我的第一個應用程序。 最初,我在獲取綁定更新時遇到一些麻煩,但是我從這里的人們那里得到了很大的幫助,並且能夠理解這個概念。 現在,我正在嘗試學習如何在我的應用程序中實現ListViews。 我遇到了與以前完全相同的問題,單擊按鈕前進一天后,我的Listview沒有更新。 同一頁面上我的stacklayout中的day值可以很好地更新,並且綁定和所有內容的寫入方式與其他頁面和數據具有相同的更新方式,但ListView仍然沒有任何反應。 另外,我使用的是一個可觀察的集合,我知道該集合應該在更改,添加或刪除項目時更新視圖。 但是,如果我打開菜單並導航到頁面的新實例,則數據會更新,因此我知道該按鈕以及其他所有功能都可以正常工作,只是視圖沒有更新。 我確信這可能是我沒有看到的愚蠢的事情,就像其他問題一樣,但是任何幫助都會很棒。 我一直被盯着看這個問題有一段時間了,但是還沒有在互聯網上找到解決方案。 提前致謝!
這是我的DrugInventoryPage.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:KingPinMobile.ViewModels"
mc:Ignorable="d"
x:Class="KingPinMobile.Views.DrugInventoryPage"
Title="Inventory">
<ContentPage.BindingContext>
<local:PlayerInventoryViewModel/>
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem Text="+24hrs" Command="{Binding PIVMOn1Turn}" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal" Padding="20">
<Label Text="Money:" HorizontalOptions="Start"/>
<Label x:Name="lblPlayerMoney" Text="{Binding Money, Mode=OneWay}" HorizontalOptions="FillAndExpand"/>
</StackLayout>
<StackLayout Padding="0">
<BoxView HeightRequest="1" HorizontalOptions="FillAndExpand" Color="Gray" />
</StackLayout>
<ListView x:Name="lvPlayerDrugs" ItemsSource="{Binding PlayerDrugs}">
<ListView.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="Drug" Grid.Row="0" Grid.Column="0" HorizontalOptions="CenterAndExpand" BackgroundColor="LightGray"/>
<Label Text="Quantity" Grid.Row="0" Grid.Column="1" HorizontalOptions="CenterAndExpand" BackgroundColor="LightGray"/>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" Grid.Row="0" Grid.Column="0"/>
<Label Text="{Binding Quantity}" Grid.Row="0" Grid.Column="1"/>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
這是DrugInventoryPage.xaml.cs:
using KingPinMobile.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace KingPinMobile.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DrugInventoryPage : ContentPage
{
public DrugInventoryPage()
{
InitializeComponent();
}
}
}
這是PlayerInventoryViewModel.cs:
using Engine;
using KingPinMobile.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;
namespace KingPinMobile.ViewModels
{
public class PlayerInventoryViewModel : HomePageViewModel
{
public PlayerInventoryModel model = new PlayerInventoryModel();
public ObservableCollection<DrugInventoryItem> Player1Drugs = new ObservableCollection<DrugInventoryItem>();
public PlayerInventoryViewModel()
{
PIVMOn1Turn = new Command(execute: PIVMOn1Turns);
Player1Drugs = model.PlayerDrugs;
}
public ICommand PIVMOn1Turn { get; private set; }
public ObservableCollection<DrugInventoryItem> PlayerDrugs
{
get { return Player1Drugs; }
set { Player1Drugs = value; OnPropertyChanged(); }
}
public void PIVMOn1Turns()
{
_model.On1Turn();
_model.refreshModel();
model.refreshPlayerInventoryModel();
CurrentDay = Math.Floor(ProgressionDirectory.CurrentGameDay.DayNumber).ToString();
Money = Convert.ToInt32(Math.Floor(World._player.PlayerMoney)).ToString();
PlayerDrugs = World._player.DrugInventory;
Player1Drugs = World._player.DrugInventory;
}
}
}
這是先前ViewModel繼承自的HomePageViewModel.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Windows.Input;
using Engine;
using Hangfire.Annotations;
using Xamarin.Forms;
namespace KingPinMobile
{
public class HomePageViewModel : INotifyPropertyChanged
{
public static HomeModel _model = new HomeModel();
public Player _player = _model.Player1;
public string Day = _model.DayText;
public string MoneyValue = _model.MoneyText;
public string CurrentLocation = _model.Player1.CurrentLocation.Name;
public HomePageViewModel()
{
OnTurn = new Command(execute: On1Turn);
}
public ICommand OnTurn { get; private set; }
public string CurrentDay
{
get { return Day; }
set { Day = value; OnPropertyChanged(); }
}
public string Money
{
get { return MoneyValue; }
set { MoneyValue = value; OnPropertyChanged(); }
}
public string PlayerLocation
{
get { return CurrentLocation; }
set { CurrentLocation = value; OnPropertyChanged(); }
}
public void On1Turn()
{
_model.On1Turn();
_model.refreshModel();
CurrentDay = Math.Floor(ProgressionDirectory.CurrentGameDay.DayNumber).ToString();
Money = Convert.ToInt32(Math.Floor(World._player.PlayerMoney)).ToString();
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
這是PlayerInventoryModel.cs:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Engine
{
public class PlayerInventoryModel : HomeModel
{
public ObservableCollection<DrugInventoryItem> PlayerDrugs = World._player.DrugInventory;
public void refreshPlayerInventoryModel()
{
PlayerDrugs = World._player.DrugInventory;
refreshModel();
}
}
}
最后,先前模型繼承的HomeModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Engine;
namespace Engine
{
public class HomeModel
{
public string DayText = Math.Floor(ProgressionDirectory.CurrentGameDay.DayNumber).ToString();
//public decimal Money = Convert.ToInt32(Math.Floor(World._player.PlayerMoney)).;
public string MoneyText = Convert.ToInt32(Math.Floor(World._player.PlayerMoney)).ToString();
public Day CurrentDay = ProgressionDirectory.CurrentGameDay;
public Player Player1 = World._player;
public string TrueDay = ProgressionDirectory.CurrentGameDay.DayNumber.ToString();
public void On1Turn()
{
Day CurrentGameDay = ProgressionDirectory.CurrentGameDay;
Advance1DAY.Advance1DAYS(CurrentGameDay);
decimal TurnsPassed = 1;
Sell.DrugsOnTurn(TurnsPassed);
ActionDirectory.OnTurn(TurnsPassed);
}
public void refreshModel()
{
DayText = Math.Floor(ProgressionDirectory.CurrentGameDay.DayNumber).ToString();
MoneyText = Convert.ToInt32(Math.Floor(World._player.PlayerMoney)).ToString();
CurrentDay = ProgressionDirectory.CurrentGameDay;
Player1 = World._player;
TrueDay = ProgressionDirectory.CurrentGameDay.DayNumber.ToString();
}
}
}
我真的不明白為什么要獲得此實現,而不是在希望另一個屬性知道更改的情況下為屬性設置備用字段並提高屬性,但是無論如何,您都返回或設置了Player1Drugs
集合。 順便說一句,為什么要在設置器中設置Player1Drugs
?
public ObservableCollection<DrugInventoryItem> PlayerDrugs
{
get { return Player1Drugs; }
set { Player1Drugs = value; OnPropertyChanged(); }
}
然而,當我告訴你,也許你應該做你的性能有一定的重構,從而你PlayerDrugs
可以知道的任何變化Player1Drugs
。
public ObservableCollection<DrugInventoryItem> PlayerDrugs => Players1Drugs;
private ObservableCollection<DrugInventoryItem> _player1Drugs;
public ObservableCollection<DrugInventoryItem> Player1Drugs
{
get { return _player1Drugs; }
set {
if(_player1Drugs == value) return;
_player1Drugs = value;
OnPropertyChanged();
OnPropertyChanged("PlayerDrugs")
}
}
或者,使用后備字段做兩個屬性(例如Player1Drugs
的上一個),然后重新排列代碼邏輯。
編輯 :運行您的示例並使它工作。 如果要觸發屬性更改,則應在PIVMon1Turns()
創建一個新的ObservableCollection
:
Player1Drugs = new ObservableCollection<DrugInventoryItem>(World.Player1.DrugInventory);
調用屬性作為發送屬性名稱
OnPropertyChanged("PlayerLocation");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.