Xamarin Forms MVVM UWP ListView Binding не работает - PullRequest
0 голосов
/ 19 февраля 2019

Я пытаюсь реализовать ContentVage MVVM с ListView, который должен быть привязан к заполненному универсальному списку объектов модели XML в ViewModel, но привязка не удалась.Показанный код вызывает API, который возвращает действительный список данных XML.Тот же код прекрасно работает, когда привязка выполняется непосредственно в коде за страницей содержимого XAML Xamarin, устанавливая ItemSource в codebehind.Как уже было сказано, проблема возникает только при попытке передать ListView через ViewModel, назначенную на страницу содержимого.Я прошел через код в ViewModel и ListView успешно заполнен, но привязка просто не работает.У меня есть другие элементы управления на странице, для которых работает привязка модели, но единственный неработающий элемент управления - это ListView.Код показан ниже:

ViewModel:

using RestDemo.Model;
using RestDemo.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.ComponentModel;
using System.Windows.Input;
using System.Collections.ObjectModel;

namespace RestDemo.ViewModel
{
    
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public ViewModel ()
        {
           GetRequest();
        }

        List<XmlPizzaDetails> _objPizzaList;
        string _selectedDescription = "Descriptions: ";
        bool _progress;
        string _cusButtonText = "Hello";

        public bool Progress
        {
            get { return _progress; }
            set { _progress = value; }
        }

        public string CusButtonText
        {
            get { return _cusButtonText; }
            set { _cusButtonText = value; }
        }

        public string SelectedDescription
        {
            get { return _selectedDescription; }
            set { _selectedDescription = value; }
        }

        public List<XmlPizzaDetails> ObjPizzaList
        {
            get { return _objPizzaList; }

            set
            {
                if (_objPizzaList != value)
                {
                    _objPizzaList = value;
                    OnPropertyChanged("ObjPizzaList");
                }
            }
        }

        public string Description
        {
            get { return _selectedDescription; }
            set { _selectedDescription = value; }
        }

        public ICommand SelectedCommand => new Command(() =>
        {
            CusButtonText = "Goodby";
        });

       event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
        {
            add
            {
            }

            remove
            {
            }
        } 

        public async void GetRequest()
        {
            if (NetworkCheck.IsInternet())
            {

                Uri geturi = new Uri("http://api.androidhive.info/pizza/?format=xml"); //replace your                       xml url
                HttpClient client = new HttpClient();
                HttpResponseMessage responseGet = await client.GetAsync(geturi);
                string response = await responseGet.Content.ReadAsStringAsync();

                //Xml Parsing
                ObjPizzaList = new List<XmlPizzaDetails>();
                XDocument doc = XDocument.Parse(response);
                foreach (var item in doc.Descendants("item"))
                {
                    XmlPizzaDetails ObjPizzaItem = new XmlPizzaDetails();
                    ObjPizzaItem.ID = item.Element("id").Value.ToString();
                    ObjPizzaItem.Name = item.Element("name").Value.ToString();
                    ObjPizzaItem.Cost = item.Element("cost").Value.ToString();
                    ObjPizzaItem.Description = item.Element("description").Value.ToString();
                    ObjPizzaList.Add(ObjPizzaItem);
                }
                Progress = false;
            }
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this,
                    new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

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:xlocal="clr-namespace:RestDemo.ViewModel"
             xmlns:local="clr-namespace:RestDemo"
             xmlns:Views="clr-namespace:RestDemo.Views"
             x:Class="RestDemo.XmlParsingPageBehavior">
    <ContentPage.BindingContext>
        <xlocal:ViewModel />
    </ContentPage.BindingContext>
    <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Views:CustomButton Grid.Row="0" Grid.Column="0" Text="HOME"  />
                <Views:CustomButton Grid.Row="0" Grid.Column="1" Text="Administrative Maintence"  />
                <Views:CustomButton Grid.Row="0" Grid.Column="2" Text="User Maintence"  />
                <Views:CustomButton Grid.Row="0" Grid.Column="3" Text="About" />
            </Grid>
            <Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Views:CustomButton Grid.Row="0" Grid.Column="0" Text="{Binding CusButtonText,                             Mode=TwoWay}">
                    <Views:CustomButton.Behaviors>
                        <local:ItemSelectedToCommandBehavior />
                    </Views:CustomButton.Behaviors>
                </Views:CustomButton>
            </Grid>
            <Frame Margin="5, 5, 5, 5" Grid.Row="2" Grid.Column="1" BackgroundColor = "Cyan">
                <ListView x:Name="PizzaListView" ItemsSource="{Binding ObjPizzaList}"  Margin="5, 0, 5,                     0" Grid.Row="2" Grid.Column="1" HorizontalOptions="FillAndExpand"                                     HasUnevenRows="True">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Grid HorizontalOptions="FillAndExpand" Margin="0,0,0,0" Padding="20">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="Auto"/>
                                    </Grid.RowDefinitions>
                                    <Label Text="{Binding Name}" HorizontalOptions="StartAndExpand"                                             Grid.Row="0" TextColor="Blue"  FontAttributes="Bold"/>
                                    <Label Text="{Binding Cost}" HorizontalOptions="StartAndExpand"                                             Grid.Row="1" TextColor="Orange"  FontAttributes="Bold"/>
                                    <Label Text="{Binding Description}"                                                                         HorizontalOptions="StartAndExpand" Grid.Row="2"                                                       TextColor="Gray"  FontAttributes="Bold"/>
                                    <BoxView HeightRequest="2" Margin="0,10,10,0"                                                               BackgroundColor="Gray" Grid.Row="3" HorizontalOptions="Fill" />
                                </Grid>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </Frame>
        </Grid>
        <ActivityIndicator x:Name="ProgressLoader" IsVisible="{Binding Progress}" IsRunning="True"/>
    </Grid>
</ContentPage>

1 Ответ

0 голосов
/ 20 февраля 2019

у меня это работает.Да, ObservableCollections - это то, что нужно, но общие списки тоже подойдут.Проблема заключается в том, что когда модель привязана, вызов WebService не завершился, поэтому, когда свойство List связано, оно по-прежнему равно нулю.Даже при обновлении на этом этапе ObservableCollection не будет работать, потому что он не был заполнен.Решение состоит в том, чтобы заполнить ObservableCollection или List для события OnAppearing страницы и связать ViewModel как BindingContext в этом событии.Мое решение ниже:

protected override async void OnAppearing()
{
    var vm = new ViewModel.ViewModel();
    if (vm == null)
        return;

    HttpClient client = new HttpClient();
    HttpResponseMessage responseGet = await client.GetAsync(vm.Geturi);
    string response = await responseGet.Content.ReadAsStringAsync();

    //Xml Parsing
    var _objPizzaList = new ObservableCollection<XmlPizzaDetails>();
    XDocument doc = XDocument.Parse(response);

    vm.GetRequest(doc);

    this.BindingContext = vm;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...