Xamarin ListView绑定无法正常工作

时间:2018-06-05 01:10:14

标签: xamarin data-binding xamarin.forms

我一直在尝试将ListView绑定到我的View模型。视图模型成功从数据库中检索5条记录,Listview似乎显示5个空白行,但是它没有显示每行中每个字段的绑定。

我花了几天时间搜索互联网,但我似乎没有做任何不同的事情。我正在使用主详细信息页面,所以我认为这可能是问题所以我将我的事件页面设置为没有主/详细情景的第一个导航页面,但无济于事。请注意,我使用Portable Ninject作为我的依赖项/ IoC。

我的App.Xamal.cs如下:

public App (params INinjectModule[] platformModules)
    {
        InitializeComponent();

        var eventsPage = new NavigationPage(new EventsPage());

        //Register core services
        Kernel = new StandardKernel(new MyAppCoreModule(), new MyAppNavModule(eventsPage.Navigation));

        //Register platform specific services
        Kernel.Load(platformModules);

        //Get the MainViewModel from the IoC
        eventsPage.BindingContext = Kernel.Get<EventsViewModel>();
        ((BaseViewModel)(eventsPage.BindingContext)).Init();

        MainPage = eventsPage;
    }

我的EventsPage.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"                          
             x:Class="MyApp.Views.EventsPage"             
             Title="Events">    
    <ContentPage.Content>        
        <ListView x:Name="Events" ItemsSource="{Binding Events}" >            
                <ListView.ItemTemplate>
                    <DataTemplate>
                    <ViewCell>
                        <Label Text="{Binding EventID}" BackgroundColor="Red" TextColor="White"
                           FontAttributes="Bold" />
                    </ViewCell>                        
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>            
    </ContentPage.Content>
</ContentPage>

我的EventsPage.xaml.cs如下:

namespace MyApp.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class EventsPage : ContentPage, IBaseViewFor<EventsViewModel>
    {
        public EventsPage ()
        {
            InitializeComponent ();
        }
        EventsViewModel _vm;
        public EventsViewModel ViewModel
        {
            get => _vm;
            set
            {
                _vm = value;
                BindingContext = _vm;
            }
        }

    }
}

我的EventsViewModel如下,它成功检索了5条记录,并为Events属性触发了OnPropertyChanged:

namespace MyApp.ViewModels
{
    public class EventsViewModel : BaseViewModel, IBaseViewModel
    {
        ObservableCollection<Event> _events;
        readonly IEventDataService _eventDataService;

        public ObservableCollection<Event> Events
        {
            get { return _events; }
            set
            {
                _events = value;
                OnPropertyChanged();
            }
        }        
        public EventsViewModel(INavService navService, IEventDataService eventDataService) : base(navService)
        {     
            _eventDataService = eventDataService;
            Events = new ObservableCollection<Event>();                
        }

        public override async Task Init()
        {
            LoadEntries();
        }
        async void LoadEntries()
        {                       
            try
            {                
                var events = await _eventDataService.GetEventsAsync();             
                Events = new ObservableCollection<Event>(events);
            }
            finally
            {

            }           
        }
    }
}

我的BaseViewModel如下:

namespace MyApp.ViewModels
{
    public abstract class BaseViewModel : INotifyPropertyChanged
    {
        protected INavService NavService { get; private set; }

        protected BaseViewModel(INavService navService)
        {
            NavService = navService;
        }

        bool _isBusy;
        public bool IsBusy
        {
            get
            {
                return _isBusy;
            }
            set
            {
                _isBusy = value;
                OnPropertyChanged();
                OnIsBusyChanged();
            }
        }

        protected virtual void OnIsBusyChanged()
        {

        }

        public abstract Task Init();

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    // Secod BaseViewModel abstract base class with a generic type that will be used to pass strongly typed parameters to the Init method
    public abstract class BaseViewModel<TParameter> : BaseViewModel
    {
        protected BaseViewModel(INavService navService) : base(navService)
        {
        }

        public override async Task Init()
        {
            await Init(default(TParameter));
        }

        public abstract Task Init(TParameter parameter);
    }
}

IBaseViewModel只是一个空白界面:

public interface IBaseViewModel
    {
    }

IBaseViewFor如下:

namespace MyApp.ViewModels
{
    public interface IBaseViewFor
    {
    }
    public interface IBaseViewFor<T> : IBaseViewFor where T : IBaseViewModel
    {
        T ViewModel { get; set; }
    }
}

我的活动模型如下:

namespace MyApp.Models
{
    public class Event
    {        
        public int EventID;    
    }
}

最后,输出的图像,你可以看到5行是用红色背景创建的,但EventID在每一行都没有绑定。我检查了数据并返回了EventID。我甚至尝试手动将记录添加到事件列表中但无济于事,请参阅下面的手册代码和图像:

async void LoadEntries()
        {                       
            try
            {               

                Events.Add((new Event() { EventID = 1 }));
                Events.Add((new Event() { EventID = 2 }));
                Events.Add((new Event() { EventID = 3 }));
                Events.Add((new Event() { EventID = 4 }));
                Events.Add((new Event() { EventID = 5 }));

            }
            finally
            {

            }           
        }

enter image description here

我花了很多时间在这上面但却无法找到这种异常的原因,有人可以请一个新的眼睛并提供帮助!

1 个答案:

答案 0 :(得分:2)

您只能绑定到公共属性 - 即,您需要一个getter

public class Event
{        
    public int EventID { get; set; } 
}