Xamarin.forms MVVM。列表视图仍为空

时间:2018-05-07 10:05:40

标签: c# data-binding xamarin.forms

我是Xamarin.Forms和MVVM的新手,并在StackOverflow上发布问题,请耐心等待。我正在尝试填写Xamarin.Forms中的listview。我首先在没有MVVM的情况下对它进行了编程,它完全像我想要的那样工作,但是现在我想进入MVVM并且它出错了,现在我的列表将不再填满。 我创建了一个viewmodel并且只将所有绑定放在viewmodel中,我还没有实现eventhandler。

这是背后代码的一部分(我还有更多的事件处理程序,但现在不相关):

    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;
        }

    }

它还有自己的viewmodel ,其中包含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 个答案:

答案 0 :(得分:0)

从可维护性的角度来看,我在这里看到了代码的一些问题。尝试将所有代码保留在视图模型中,而不是视图模型和后面的代码。理想情况下,您的代码背后不包含任何内容,如果有的话,它与视觉内容有关。

无论如何,关于你的问题:你每次都在创建一个新的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;
    }
}

现在应该显示您的数据。