2016-11-18 121 views
0

不起作用在我们Xamarin的应用程序,我们有一个ListView,显示用户选择,他们将被带到该调查的详情页的调查Surveys.If的列表。为此,我们在SelectedItem属性上使用TwoWay绑定,并将控制器添加到控制器中的SelectedItem属性中。Xamarin的ListView双向绑定在iOS

Xaml-

<ListView x:Name= "surveyList" ItemsSource= "{Binding Surveys}" SelectedItem= "{Binding SelectedSurvey, Mode=TwoWay}" BackgroundColor= "White" HorizontalOptions= "Fill" SeparatorColor= "Gray" RowHeight= "50" > 

C# -

private SurveyListItem _selectedSurvey; 
public SurveyListItem SelectedSurvey 
{ 
    get { return _selectedSurvey; } 
    set 
    { 
     _selectedSurvey = value; 
     if (_selectedSurvey == null) 
     { 
      NotifyPropertyChanged(); 
      return; 
     } 
     OnSurveySelected(_selectedSurvey); 
     _selectedSurvey = null; 
     NotifyPropertyChanged(); 
    } 
} 

这工作找到AndroidiOS不起作用。点击列表中的项目不会设置_selectedSurvey或致电设置者SelectedSurvey

我可以做一个快速修复,并将其改为某种点击手势,但我们在需要多选的应用程序的其他地方使用ListView,并且将所有这些改为点击手势将是一种痛苦。

任何想法,为什么这会为Android工作,但不是iOS

编辑 -

完全Xaml-

<?xml version = "1.0" encoding= "utf-8" ?> 

< TabbedPage xmlns = "http://xamarin.com/schemas/2014/forms" 

      xmlns:x= "http://schemas.microsoft.com/winfx/2009/xaml" 

       x:Class= "MyApp.View.ModuleContentPage" 

      xmlns:vm= "clr-namespace:MyApp.ViewModel;assembly=MyApp" 

      xmlns:local= "clr-namespace:MyApp.View;assembly=MyApp" 

      Title= "Module Content Render" > 

    <TabbedPage.Children> 

    < ContentPage Title= "Summary" IsEnabled= "False" > 

     <ContentPage.Content> 

     < StackLayout Padding= "20, 20, 20, 0" > 

      < Label Text= "To Do: Render Module Content Here." ></ Label > 

     </ StackLayout > 

     </ ContentPage.Content > 

    </ ContentPage > 

    < ContentPage Title= "Related" > 

     <ContentPage.Content> 

     < StackLayout Padding= "20, 20, 20, 0" > 

      < Label Text= "To Do: Render Related Content Here." ></ Label > 

     </ StackLayout > 

     </ ContentPage.Content > 

    </ ContentPage > 

    < ContentPage Title= "Surveys" IsEnabled= "False" > 

     <ContentPage.Content> 

     < StackLayout Padding= "20" > 

      < ListView x:Name= "surveyList" ItemsSource= "{Binding Surveys}" SelectedItem= "{Binding SelectedSurvey, Mode=TwoWay}" BackgroundColor= "White" HorizontalOptions= "Fill" SeparatorColor= "Gray" RowHeight= "50" > 

      <ListView.Header> 

       < StackLayout Padding= "0, 0, 0, 10" VerticalOptions= "Center" > 

        < Label Text= "Surveys" FontSize= "20" TextColor= "Gray" LineBreakMode= "NoWrap" /> 

       </ StackLayout > 

      </ ListView.Header > 

      <ListView.ItemTemplate> 

       <DataTemplate> 

       <ViewCell> 

        <ViewCell.View> 

        < StackLayout VerticalOptions= "Center" > 

         < Grid ColumnSpacing= "20" > 

         <Grid.RowDefinitions> 

          < RowDefinition Height= "*" /> 

         </ Grid.RowDefinitions > 

         <Grid.ColumnDefinitions> 

          < ColumnDefinition Width= "*" /> 

          < ColumnDefinition Width= "50" /> 

         </ Grid.ColumnDefinitions > 

         < Label Text= "{Binding HydratedSurvey.Name}" FontSize= "12" TextColor= "Black" FontAttributes= "Bold" Grid.Row= "0" Grid.Column= "0" /> 

         < Label Text= "{Binding SurveyInstanceCount}" FontSize= "12" TextColor= "Green" FontAttributes= "Bold" Grid.Row= "0" Grid.Column= "1" /> 

         </ Grid > 

        </ StackLayout > 

        </ ViewCell.View > 

       </ ViewCell > 

       </ DataTemplate > 

      </ ListView.ItemTemplate > 

      </ ListView > 

     </ StackLayout > 

     </ ContentPage.Content > 

    </ ContentPage > 

    </ TabbedPage.Children > 

</ TabbedPage > 

代码Behind-

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

using Xamarin.Forms; 

namespace MyApp.View 
{ 
    public partial class ModuleContentPage : TabbedPage 
    { 
     private Page PreviousPage { get; set; } 

     public ModuleContentPage() 
     { 
      InitializeComponent(); 

      // TODO hard coded to disabled the first two tabs and select Surveys. Remove when other tabs are finished 
      DisableTab(Children[0]); 
      DisableTab(Children[1]); 

      //Children[0].IsEnabled = false; 
      //Children[1].IsEnabled = false; 
      //PreviousPage = Children[2]; 
      //CurrentPage = PreviousPage; 
      CurrentPage = Children[2]; 

      CurrentPageChanged += ModuleContentPage_CurrentPageChanged; 
      PagesChanged += ModuleContentPage_PagesChanged; 
     } 

     private void DisableTab(Page page) 
     { 
      page.IsEnabled = false; 
      //page.Unfocus(); 
      page.Opacity = 50.0; 
     } 

     private void ModuleContentPage_PagesChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
     { 
      CurrentPage = Children[2]; 
     } 

     private void ModuleContentPage_CurrentPageChanged(object sender, EventArgs e) 
     { 
      CurrentPage = Children[2]; 
     } 
    } 
} 

**视图模型 - **

using Newtonsoft.Json; 
using MyApp.DataModel.TransferObjects; 
using MyApp.DataAccess.UoW; 
using MyApp.Services; 
using MyApp.SQLiteAccess.Repository; 
using MyApp.SQLiteAccess.Tables; 
using MyApp.ViewModel; 
using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Input; 
using Xamarin.Forms; 

namespace MyApp.ViewModel 
{ 
    public class SurveyListItem : ViewModelBase 
    { 
     public SurveyDTO HydratedSurvey { get; set; } 
     private int _surveyInstanceCount; 
     public int SurveyInstanceCount { get { return _surveyInstanceCount; } set { _surveyInstanceCount = value; NotifyPropertyChanged(); } } 
    } 

    public class ModuleContentPageViewModel : ViewModelBase 
    { 
     private ModuleHydratedDTO _module; 
     public ModuleHydratedDTO Module { get { return _module; } set { _module = value; NotifyPropertyChanged(); } } 

     private ModuleContentHydratedDTO _moduleContent; 
     public ModuleContentHydratedDTO ModuleContent { get { return _moduleContent; } set { _moduleContent = value; NotifyPropertyChanged(); } } 

     SqlSurveyInstanceRepository _sqlSurveyInstanceRepository; 
     SqlSurveyInstanceRepository SqlSurveyInstanceRepository { get { return _sqlSurveyInstanceRepository ?? (_sqlSurveyInstanceRepository = new SqlSurveyInstanceRepository()); } } 

     private ObservableCollection<SurveyListItem> _surveys; 
     public ObservableCollection<SurveyListItem> Surveys { get { return _surveys; } set { _surveys = value; NotifyPropertyChanged(); } } 

     public ModuleContentPageViewModel(ModuleHydratedDTO module, ModuleContentHydratedDTO moduleContent) : base() 
     { 
      _module = module; 
      _moduleContent = moduleContent; 
      _surveys = GetSurveys(); 

      MessagingCenter.Subscribe<Stores.SurveyStore, SurveyDTO>(this, "UpdateSurveyInstanceCount", (sender, hydratedSurvey) => 
      { 
       SurveyListItem survey = _surveys.FirstOrDefault(s => s.HydratedSurvey.SurveyId == hydratedSurvey.SurveyId); 
       if (survey != null) 
       { 
        survey.SurveyInstanceCount = UoW.SurveyInstances.GetCountForSurveyIdAsync(hydratedSurvey.MasterSurveyId ?? hydratedSurvey.SurveyId, ModuleContent.ModuleContentId).Result; 
        NotifyPropertyChanged(); 
       } 
      }); 
     } 

     private ObservableCollection<SurveyListItem> GetSurveys() 
     { 
      ObservableCollection<SurveyListItem> surveyList = new ObservableCollection<SurveyListItem>(); 
      List<SurveyDTO> surveys = UoW.Surveys.GetHydratedSurveysForUser(_module.Module.ModuleId); 

      if (surveys.Count > 0) 
      { 
       foreach (var survey in surveys) 
       { 
        SurveyListItem item = new SurveyListItem(); 
        item.HydratedSurvey = survey; 
        item.SurveyInstanceCount = UoW.SurveyInstances.GetCountForSurveyIdAsync(survey.MasterSurveyId.HasValue ? survey.MasterSurveyId.Value : survey.SurveyId, ModuleContent.ModuleContentId).Result; 
        surveyList.Add(item); 
       } 
      } 
      return surveyList; 
     } 

     private SurveyListItem _selectedSurvey; 
     public SurveyListItem SelectedSurvey 
     { 
      get { return _selectedSurvey; } 
      set 
      { 
       _selectedSurvey = value; 
       if (_selectedSurvey == null) 
       { 
        NotifyPropertyChanged(); 
        return; 
       } 
       OnSurveySelected(_selectedSurvey); 
       _selectedSurvey = null; 
       NotifyPropertyChanged(); 
      } 
     } 

     private void OnSurveySelected(SurveyListItem selectedSurvey) 
     { 
      NavigationService.PushAsync(new SurveyInstanceListVM(selectedSurvey.HydratedSurvey, _moduleContent.ModuleContentId), selectedSurvey.HydratedSurvey.Name); 
     } 
    } 
} 

希望帮助

编辑编辑 -

这里是frankenstiened视图模型/ viewmodelbase组合。

using MyApp.DataModel.TransferObjects; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using MyApp.ViewModelFramework.Spooling; 

namespace MyApp.ViewModel 
{ 
    public class SurveyListItem 
    { 
     public string Name { get { return "foo"; } set { var x = value; } } 
     private int _surveyInstanceCount; 
     public int SurveyInstanceCount { get { return _surveyInstanceCount; } set { _surveyInstanceCount = value; } } 
    } 

    public class ModuleContentPageViewModel 
    { 
     private ObservableCollection<SurveyListItem> _surveys; 
     public ObservableCollection<SurveyListItem> Surveys { get { return _surveys; } set { _surveys = value; NotifyPropertyChanged(); } } 


     public ModuleContentPageViewModel(ModuleHydratedDTO module, ModuleContentHydratedDTO moduleContent) : base() 
     { 
      _surveys = GetSurveys(); 
     } 

     private ObservableCollection<SurveyListItem> GetSurveys() 
     { 
      ObservableCollection<SurveyListItem> surveyList = new ObservableCollection<SurveyListItem>(); 
      surveyList.Add(new SurveyListItem()); 
      return surveyList; 
     } 

     private SurveyListItem _selectedSurvey; 
     public SurveyListItem SelectedSurvey 
     { 
      get { return _selectedSurvey; } 
      set 
      { 
       _selectedSurvey = value; 
       if (_selectedSurvey == null) 
       { 
        NotifyPropertyChanged(); 
        return; 
       } 
       _selectedSurvey = null; 
       NotifyPropertyChanged(); 
      } 
     } 

     public void NotifyPropertyChanged([CallerMemberName] string propertyName = "") 
     { 
      InvokeNotifyPropertyChanged(propertyName); 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     public NotifyPropertyChangedSpooler NotificationSpooler = new NotifyPropertyChangedSpooler(); 

     private NotificationPropertyChangedStateEnum _notificationPropertyChangedState = NotificationPropertyChangedStateEnum.Active; 

     // Gets and sets change notification spooling and blocking features. 
     public NotificationPropertyChangedStateEnum NotificationPropertyChangedState 
     { 
      get { return _notificationPropertyChangedState; } 
      set 
      { 
       _notificationPropertyChangedState = value; 
       if (_notificationPropertyChangedState == NotificationPropertyChangedStateEnum.Active && !NotificationSpooler.IsEmpty) 
       { 
        NotificationSpooler.Unwind(); 
       } 
       NotifyPropertyChanged(); 

      } 
     } 


     void InvokeNotifyPropertyChanged(string propertyName) 
     { 
      switch (NotificationPropertyChangedState) 
      { 
       case NotificationPropertyChangedStateEnum.Active: 
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
        break; 
       case NotificationPropertyChangedStateEnum.Spooling: 
        NotificationSpooler.Enqueue(this, propertyName); 
        break; 
       case NotificationPropertyChangedStateEnum.Inactive: 
        break; 
      } 
     } 
    } 

    public enum NotificationPropertyChangedStateEnum 
    { 
     Inactive = 0, 
     Active = 1, 
     Spooling = 3 
    } 
} 
+0

你如何定义你的列表?它只是一个列表或ObservableCollection?更多的代码和xaml将有所帮助。理想情况下,如果您可以将完整的代码发布到包含模型的页面和代码后面,我们可能会帮助更快 –

+0

这是一个ObservableCollection。我更新了页面xaml,后面的代码,并查看模型 –

+0

即将尝试......您是在设备上还是在模拟器上测试?什么是iOS版本? –

回答

1

经过一番调查发现,该网页在xaml中被禁用,并且从未在xaml和代码后面启用过。由于某种原因,它在Android中不是问题(这是一种错误,应该调查更多为什么)。

+0

谢谢尤里,因为花了这么多时间来研究这个并帮助我们解决这个问题! - 如果我能给这个家伙超过1+我会:) –

+0

@MicahWilliamson我的荣幸 –