Xamarin.forms MVVM。列表视图仍然为空
Posted
技术标签:
【中文标题】Xamarin.forms MVVM。列表视图仍然为空【英文标题】:Xamarin.forms MVVM. Listview remains empty 【发布时间】:2018-10-17 02:35:36 【问题描述】:我对 Xamarin.Forms 和 MVVM 非常陌生,并且在 *** 上发布了问题,所以请多多包涵。我正在尝试在 Xamarin.Forms 中填充列表视图。我第一次在没有 MVVM 的情况下对其进行了编程,一切都像我想要的那样工作,但现在我想进入 MVVM,这就是它出错的地方,现在我的列表不会再填满了。 我做了一个viewmodel,只把所有的绑定都放在了viewmodel中,还没有实现eventhandlers。
这是背后的代码的一部分(我还有几个事件处理程序,但现在不相关):
namespace CCXamarinApp
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PatientsWithTagPage : ContentPage
public PatientsWithTagPage()
BindingContext = new PatientsWithTagViewModel();
InitializeComponent();
(BindingContext as PatientsWithTagViewModel).GetAllPatients();
if((BindingContext as PatientsWithTagViewModel).IsEmptyPatientList)
HandleEmptyList();
else
(BindingContext as PatientsWithTagViewModel).SortAndShowPatients();
private void SearchBar_OnTextChanged(object sender, TextChangedEventArgs e)
(BindingContext as PatientsWithTagViewModel).Searching(e.NewTextValue);
...
这是我的 XAML 页面:
<SearchBar x:Name="SearchBar" Placeholder="Zoek op naam of plaats..." HeightRequest="25" Margin="10"
TextChanged="SearchBar_OnTextChanged"/>
<Label Text="Binding LastRefreshed" FontAttributes="Italic" FontSize="15" />
<Label x:Name="LabelEmptyList" FontSize="17" Text="Geen gegevens gevonden" FontAttributes="Bold"
IsVisible="False" />
<ListView x:Name="PatientListView" HasUnevenRows="True" SeparatorColor="Accent"
VerticalOptions="FillAndExpand" IsPullToRefreshEnabled="True" IsRefreshing="Binding IsFetchingData, Mode=TwoWay"
Refreshing="PatientListView_OnRefreshing" SelectedItem="Binding SelectedPatient, Mode=TwoWay"
ItemSelected="PatientListView_OnItemSelected" ItemsSource="Binding Patients"
IsVisible="True" BackgroundColor="Aqua">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Spacing="4">
<StackLayout Orientation="Horizontal" Margin="10,7,10,1">
<Label Text="Binding FullName" FontAttributes="Bold" FontSize="16" />
<Label Text="Binding DisplayTimeOfLastScan, StringFormat='0'"
HorizontalOptions="EndAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal" Margin="10,0,10,7">
<Label Text="Binding LastLocation" HorizontalOptions="Start" />
<Label Text="Binding DisplayDurationSinceLastScan, StringFormat='al 0'"
HorizontalOptions="EndAndExpand" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
这是我的 viewmodel(不是所有代码,而是最相关的代码)。它派生的 BaseViewModel 来自 nuget 包“Refractored.Mvvmhelpers”:
class PatientsWithTagViewModel : BaseViewModel
public ObservableCollection<PatientViewModel> Patients get; private set; = new ObservableCollection<PatientViewModel>();
private PatientViewModel selectedPatient;
public PatientViewModel SelectedPatient
get => selectedPatient;
set => SetProperty(ref selectedPatient, value);
private readonly JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
DateFormatString = "dd-MM-yyyTH:mm",
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
;
public bool IsEmptyPatientList => Patients.Count == 0;
private string testJson = "[\"firstName\":\"P.\",\"lastName\":\"Selie\",\"tag\":\"tagId\":\"124\",\"tagSerialNumber\":\"ABC135\",\"scans\":[\"location\":\"Tuin\",\"dateTime\":\"May01,2018,10:10\",\"location\":\"Eetzaal\",\"dateTime\":\"May02,2018,10:15\",\"location\":\"Gang\",\"dateTime\":\"May02,2018,11:10\",\"location\":\"Kamer23\",\"dateTime\":\"May02,2018,12:09\"],\"id\":\"dcc4fe9929b3681f\"," +
"\"firstName\":\"W.\",\"lastName\":\"Janssens\",\"tag\":\"tagId\":\"132\",\"tagSerialNumber\":\"ABC167\",\"scans\":[\"location\":\"Kamer23\",\"dateTime\":\"May01,2018,23:39\",\"location\":\"Gang\",\"dateTime\":\"May02,2018,04:10\",\"location\":\"Eetzaal\",\"dateTime\":\"May02,2018,04:11\",\"location\":\"Gang\",\"dateTime\":\"May02,2018,04:20\",\"location\":\"Kamer23\",\"dateTime\":\"May02,2018,04:22\"],\"id\":\"a6dac28475327922\"]";
public void GetAllPatients()
IsFetchingData = true;
try
Patients = new ObservableCollection<PatientViewModel>(
JsonConvert.DeserializeObject<ObservableCollection<PatientViewModel>>(testJson,
jsonSerializerSettings));
catch(Exception e)
Console.WriteLine("*****ERROR kon API niet ophalen");
Console.WriteLine(e.Message);
finally
IsFetchingData = false;
这是我使用的模型:
public class Patient : ObservableObject
public string FirstName get; set;
public string LastName get; set;
public Tag Tag get; set;
public List<Scan> Scans get; set;
public string Id get; set;
public override string ToString()
return LastName + ", " + FirstName;
它也有自己的自己的视图模型,具有DisplayDurationSinceLastScan
之类的属性,但我认为这里不相关,如果您认为相关,请告诉我。
因此,使用此代码,我得到了我的页面,但列表中似乎没有项目,如果我调试,患者充满了项目,所以它根本不是空的,但我猜绑定出了点问题,但没有报错。
Here is a picture of what I get: the listview is shown (I added a blue background so I would know if the listview was visible or not), but there are no items in there. Still Patients is filled when I debug the app.
有人看到我犯的错误吗?
【问题讨论】:
【参考方案1】:从可维护性的角度来看,我发现您的代码存在一些问题。尝试将所有代码保留在视图模型中,而不是同时保留视图模型和代码。理想情况下,您的代码不包含任何内容,如果有的话,它与视觉事物完全相关。
无论如何,关于你的问题:你每次都在创建一个新的ObservableCollection
。这打破了绑定。只需将新的ObservableCollection
保留在顶部,然后当新数据进入时,清除它并重新填充它。像这样:
public void GetAllPatients()
IsFetchingData = true;
try
var resultPatients = JsonConvert.DeserializeObject<ObservableCollection<PatientViewModel>>(testJson, jsonSerializerSettings);
Patients.Clear();
foreach (var patient in resultPatients)
Patients.Add(patient);
catch(Exception e)
Console.WriteLine("*****ERROR kon API niet ophalen");
Console.WriteLine(e.Message);
finally
IsFetchingData = false;
您的数据现在应该会显示出来。
【讨论】:
谢谢,这成功了!你对我背后的代码有一个很好的观点,但我试图指出我还没有完成 MVVM 的实现,但显然我不够清楚:) 所以我很清楚我的代码背后需要一些重构,无论如何谢谢指出来! 现在我知道为什么我做了新的 ObservableCollection:如果我使用 linq 然后填充列表视图并将其转换为 observablecollection 我得到“System.InvalidExcpetion:指定的转换无效”。这就是我放置 new ObservableCollection 的原因,因为它没有给出任何错误。知道如何解决这个问题吗? 我并不是想变得聪明,实际上只是指出可以改进一些事情以使您走上正轨,但很高兴听到您在这方面!让我们将您的下一个问题离线。您可以直接通过 gerald@verslu.is 与我联系吗?我们也可以说荷兰语;-)以上是关于Xamarin.forms MVVM。列表视图仍然为空的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin.Forms MVVM TapGestureRecognizer 到 ListView 的 ViewCell 中的标签(在部分文件中)