ListView不滚动与分组 [英] ListView is not scrolling with grouping

查看:72
本文介绍了ListView不滚动与分组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I simply changed my ListView to use grouping, but now I can't use ScrollTo anymore.

我已经创建了一个简单的应用程序,因此您可以看到问题.

I have create a simple app, so you can see the problem.

XAML页面看起来像(目前我不在我的应用程序中使用XAML,但我将在即将发布的版本中使用它.)

The XAML-page looks like (I am not using XAML in my app at the moment, but I will in an upcoming version).

<?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>

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

And the code-behind file for the example looks like this

[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)模拟来自服务器的响应,但我认为这并不重要.

I use Task.Delay(5000) to simulate a response from the server, but I do not think, it matters.

更新

我发现,问题出在我的ScrollTo通话中,其中ScrollTo(group.First(), group.Key, ScrollToPosition.Start, false);是用Key而不是仅使用组来调用的.

I figured out, the problem was in my ScrollTo-call, where ScrollTo(group.First(), group.Key, ScrollToPosition.Start, false); was called with the Key instead of just the group.

如果首先创建分组(而不将其添加到ViewModel),则必须在随后的ViewModel中找到正确的模型.因为否则找不到正确的ObservableCollection

If you create the grouping first (without adding it to the ViewModel), you have to find the correct model in the ViewModel afterwards. As it otherwise does not find the correct ObservableCollection

推荐答案

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

I have tested your code and reproduced your issue. The problem is you have passed the wrong parameter to ScrollTo method.

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

ScrollTo方法的group参数是ListView.ItemsSource中的组.但是您通过了group.Key.因此,该方法不会像预期的那样令人兴奋.请按如下所示修改代码.

The group parameter of ScrollTo method is the group from your ListView.ItemsSource. But your passed a group.Key. So the method will not be excited as expect. Please modify the code like following.

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

这篇关于ListView不滚动与分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆