【问题标题】:ListView is not scrolling with groupingListView 不滚动分组
【发布时间】:2017-08-16 05:36:26
【问题描述】:

我只是将ListView 更改为使用分组,但现在我不能再使用ScrollTo

我已经创建了一个简单的应用程序,所以你可以看到问题。

XAML 页面看起来像(我目前没有在我的应用程序中使用 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:local="clr-namespace:ScrollListExample"
   x:Class="ScrollListExample.ProjectPage">

   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition Height="*" />
      </Grid.RowDefinitions>

      <ListView x:Name="ProjectsListView" HasUnevenRows="True" IsGroupingEnabled="True" ItemsSource="{Binding Projects}">
         <ListView.GroupHeaderTemplate>
            <DataTemplate>
               <ViewCell>
                  <Label Text="{Binding Path=Key}" />
               </ViewCell>
            </DataTemplate>
         </ListView.GroupHeaderTemplate>
         <ListView.ItemTemplate>
            <DataTemplate>
               <ViewCell>
                  <Grid>
                     <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="Auto" />
                     </Grid.ColumnDefinitions>
                     <Label Grid.Column="0" Grid.Row="0" LineBreakMode="TailTruncation" Text="{Binding Path=ProjectName}" />
                     <Label Grid.Column="0" Grid.Row="1" Text="{Binding Path=ProjectReference, StringFormat='Sag: {0}'}" />
                     <Label Grid.Column="0" Grid.Row="2" Text="{Binding Path=CustomerName}" />
                     <Label Grid.Column="0" Grid.Row="3" Text="{Binding Path=FullAddress}" />
                     <Label Grid.Column="1" Grid.Row="0" Text="{Binding Path=StartTime}" />
                  </Grid>
               </ViewCell>
            </DataTemplate>
         </ListView.ItemTemplate>
      </ListView>
   </Grid>

</ContentPage>

示例的代码隐藏文件如下所示

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ProjectPage : ContentPage
{
   public ProjectPage()
   {
      InitializeComponent();
      BindingContext = new ProjectsViewModel();
   }

   protected override void OnAppearing()
   {
      base.OnAppearing();

      Acr.UserDialogs.UserDialogs.Instance.ShowLoading();

      var projects = Newtonsoft.Json.JsonConvert.DeserializeObject<IList<ProjectDto>>("[{\"ProjectName\":\"Test sag\",\"ProjectReference\":\"10072\",\"CustomerName\":\"Test firma\",\"FullAddress\":\"Testvej 3\",\"StartDate\":\"2017-02-02T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"aaa\",\"ProjectReference\":\"10077\",\"CustomerName\":\"Test firma\",\"FullAddress\":\"Testvej 12\",\"StartDate\":\"2017-02-08T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10082\",\"CustomerName\":\"Test firma\",\"FullAddress\":\"Testvej 50\",\"StartDate\":\"2017-02-16T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10085\",\"CustomerName\":\"Testvej boligselskab\",\"FullAddress\":\"Testvej 14\",\"StartDate\":\"2017-02-24T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10086\",\"CustomerName\":\"Testing\",\"FullAddress\":\"Testevej 14\",\"StartDate\":\"2017-02-27T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test1\",\"ProjectReference\":\"10087\",\"CustomerName\":\"Plejecenter testlyst\",\"FullAddress\":\"Testlystvej 11\",\"StartDate\":\"2017-02-27T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test2\",\"ProjectReference\":\"10088\",\"CustomerName\":\"Charlie\",\"FullAddress\":\"Testvej 50\",\"StartDate\":\"2017-02-27T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10089\",\"CustomerName\":\"Standard Debitor\",\"FullAddress\":\"[Mangler]\",\"StartDate\":\"2017-03-16T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10090\",\"CustomerName\":\"Standard Debitor\",\"FullAddress\":\"[Mangler]\",\"StartDate\":\"2017-03-16T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10091\",\"CustomerName\":\"Standard Debitor\",\"FullAddress\":\"[Mangler]\",\"StartDate\":\"2017-03-16T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10092\",\"CustomerName\":\"Tester\",\"FullAddress\":\"Testvej 11\",\"StartDate\":\"2017-03-16T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10093\",\"CustomerName\":\"Plejehjemmet test\",\"FullAddress\":\"Testvej 90\",\"StartDate\":\"2017-03-16T00:00:00\",\"StartTime\":\"\"},{\"ProjectName\":\"Test\",\"ProjectReference\":\"10094\",\"CustomerName\":\"Plejehjemmet test\",\"FullAddress\":\"Testvej 90\",\"StartDate\":\"2017-03-16T00:00:00\",\"StartTime\":\"\"}]");

      var viewModel = BindingContext as ProjectsViewModel;
      if (viewModel != null)
         viewModel.OriginalProjects = projects;

      Acr.UserDialogs.UserDialogs.Instance.ShowLoading("Loading");

      Task.Delay(5000).ContinueWith((x) =>
      {
          Device.BeginInvokeOnMainThread(Acr.UserDialogs.UserDialogs.Instance.HideLoading);

         Search();
      });
   }

   private void Search(string inputVal = null)
   {
      var viewModel = BindingContext as ProjectsViewModel;

      if (viewModel != null)
      {
         var projects = viewModel.OriginalProjects.Where(p => !string.IsNullOrEmpty(inputVal) ? p.ProjectName.Contains(inputVal) : true);

         var orderedProjects = projects.OrderBy(p => p.StartDate);

         Device.BeginInvokeOnMainThread(() =>
         {
            foreach (ProjectDto project in orderedProjects)
            {
               var coll = viewModel.Projects.FirstOrDefault(c => c.Key == project.StartDate);

               if (coll == null)
                  viewModel.Projects.Add(coll = new ObservableCollectionWithDateKey { Key = project.StartDate });

               coll.Add(project);
            }

            var group = viewModel.Projects.LastOrDefault();
            if (group != null)
               ProjectsListView.ScrollTo(group.First(), group.Key, ScrollToPosition.Start, false);
         });
      }
   }
}

class ProjectsViewModel : INotifyPropertyChanged
{
   private ObservableCollection<ObservableCollectionWithDateKey> _projects;

   public event PropertyChangedEventHandler PropertyChanged;

   public IEnumerable<ProjectDto> OriginalProjects { get; set; }

   public ObservableCollection<ObservableCollectionWithDateKey> Projects
   {
      get { return _projects; }
      set
      {
         _projects = value;
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Projects)));
      }
   }

   public ProjectsViewModel()
   {
      Projects = new ObservableCollection<ObservableCollectionWithDateKey>();
   }
}

public class ProjectDto : INotifyPropertyChanged
{
   public string ProjectName { get; set; }
   public string ProjectReference { get; set; }
   public string CustomerName { get; set; }
   public string FullAddress { get; set; }
   public DateTime StartDate { get; set; }
   public string StartTime { get; set; }

   public event PropertyChangedEventHandler PropertyChanged;
}

class ObservableCollectionWithDateKey : ObservableCollection<ProjectDto>
{
   public DateTime Key { get; set; }
}

我使用Task.Delay(5000) 来模拟来自服务器的响应,但我不认为这很重要。

更新

我发现,问题出在我的ScrollTo-call 中,其中ScrollTo(group.First(), group.Key, ScrollToPosition.Start, false); 是用密钥而不是组调用的。

如果您先创建分组(不将其添加到 ViewModel),则必须随后在 ViewModel 中找到正确的模型。因为它没有找到正确的 ObservableCollection

【问题讨论】:

  • 也许我错了,但你应该滚动到你的“物理”项目。我没有分组,但我的代码如下所示:BranchesAndTagsList.ScrollTo(BranchesAndTagsList.ItemsSource.Cast&lt;object&gt;().ToList()[_index], ScrollToPosition.Center, true);

标签: c# android xamarin uwp xamarin.forms


【解决方案1】:

我已经测试了您的代码并重现了您的问题。问题是您将错误的参数传递给ScrollTo 方法。

ProjectsListView.ScrollTo(group.First(), group.Key, ScrollToPosition.Start, false);

ScrollTo 方法的group 参数是来自您的ListView.ItemsSource 的组。但是你通过了group.Key。所以该方法不会像预期的那样兴奋。请修改如下代码。

Device.BeginInvokeOnMainThread(() =>
 {
     foreach (ProjectDto project in orderedProjects)
     {
         var coll = viewModel.Projects.FirstOrDefault(c => c.Key == project.StartDate);

         if (coll == null)
             viewModel.Projects.Add(coll = new ObservableCollectionWithDateKey { Key = project.StartDate });

         coll.Add(project);
     }
 var group = viewModel.Projects.Last();
 if (group != null)
     ProjectsListView.ScrollTo(group.First(), group, ScrollToPosition.Start, false);
});

【讨论】:

  • 不知何故它在我的示例中起作用,但在我的真实应用中却不起作用:(
  • 您是否尝试在您的真实应用中将group 传递给ScrollTo 方法?
  • 是的,但我发现,在滚动到它之前,我必须在 ViewModel 中查找该组。如果我没有为 UWP 设置 Task.Delay(200),我会收到 UnhandledException。我尝试将ScrollTo 包装在try-catch 中,但我无法在其中捕捉到它:( 你知道我能做什么吗?
  • 我无法通过您的分段描述来理解您的观点。我建议您可以创建一个新线程来阐明您的要求。
猜你喜欢
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 2019-10-18
  • 1970-01-01
相关资源
最近更新 更多