在Ios ListView中,当在xamarin.forms中更新项目源时,会自动滚动到顶部。保持ios中的滚动位置

时间:2017-03-22 10:11:55

标签: ios uitableview xamarin xamarin.ios xamarin.forms

我正在研究xamarin.forms 。我正面临一个问题。我有一个ListView。我将List对象作为ItemSource提供给该listView而没有任何MVVM模式(不遵循MVVM)。列表对象在项目点击或图像手势点击上更新,然后我再次将项目源提供给Listview。

在ios中,当我将项目源重新绑定到listview时,自动滚动到顶部。因此,用户无法看到所选项目。

在Android中,它的工作非常完美。

<ListView x:Name="lstLeaveNotificationDetails" HorizontalOptions="FillAndExpand" HasUnevenRows="True"
                  VerticalOptions="FillAndExpand" SeparatorVisibility="None" BackgroundColor="Transparent"
                  AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" IsVisible="false">
          <ListView.ItemTemplate>
            <DataTemplate>
              <ViewCell>
                <ViewCell.View>
                  <StackLayout x:Name="StkForListItems" ClassId="{Binding TapId}">
                    <!--Left Side Orange Color Padding-->
                    <StackLayout Padding="4,0,0,0" BackgroundColor="{Binding BgMainStackColor}">
                      <StackLayout  BackgroundColor="{Binding BgColor}" HorizontalOptions="Start">
                        <Grid Padding="3" HorizontalOptions="StartAndExpand" VerticalOptions="Center" RowSpacing="1" ColumnSpacing="0">
                          <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                          </Grid.RowDefinitions>
                          <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1*" />
                            <ColumnDefinition Width="3*" />
                            <ColumnDefinition Width="3*" />
                            <ColumnDefinition Width="3*" />
                          </Grid.ColumnDefinitions>

                          <StackLayout Grid.Row="0" Grid.Column="0"  Grid.RowSpan="5" HorizontalOptions="Center" VerticalOptions="Center" >
                            <ffimageloading:CachedImage Source="{Binding CheckSelect}" Aspect="Fill" ClassId="{Binding TapId}" HorizontalOptions="Center" VerticalOptions="Center" >
                              <ffimageloading:CachedImage.GestureRecognizers>
                                <TapGestureRecognizer Tapped="img_Tapped" NumberOfTapsRequired="1" />
                              </ffimageloading:CachedImage.GestureRecognizers>
                            </ffimageloading:CachedImage>
                          </StackLayout>

                          <StackLayout Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="3">
                            <Label Text="{Binding EmpNm}" TextColor="Black" FontSize="Medium" FontAttributes="Bold"/>
                          </StackLayout>

                          <Label Text="From" Grid.Row="1" Grid.Column="1"  TextColor="#B0B0B0" HorizontalOptions="StartAndExpand" VerticalOptions="Start"  FontSize="Small"/>
                          <Label Text="To" Grid.Row="1" Grid.Column="2"  TextColor="#B0B0B0" HorizontalOptions="StartAndExpand" VerticalOptions="Start"  FontSize="Small"/>
                          <Label Text="Leave Days" Grid.Row="1"  Grid.Column="3"  TextColor="#B0B0B0" HorizontalOptions="StartAndExpand" VerticalOptions="Start"  FontSize="Small"/>

                          <Label Text="{Binding FromDate}" Grid.Row="2"  Grid.Column="1" TextColor="Black" HorizontalOptions="StartAndExpand"    FontSize="Small"  />
                          <Label Text="{Binding ToDate}" Grid.Row="2"   Grid.Column="2" TextColor="Black" HorizontalOptions="StartAndExpand"   FontSize="Small"  />
                          <Label Text="{Binding NoOfLeave}" Grid.Row="2"  Grid.Column="3" TextColor="Black" HorizontalOptions="StartAndExpand"   FontSize="Small"  />

                          <StackLayout  Grid.Row="3"  Grid.Column="1"  Grid.ColumnSpan="3" VerticalOptions="EndAndExpand" HorizontalOptions="Start">
                            <Label Text="Reason" TextColor="#b0b0b0"   FontSize="Small"/>
                          </StackLayout>

                          <StackLayout  Grid.Row="4" Grid.Column="1"   Grid.ColumnSpan="3" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand">
                            <Label Text="{Binding Reason}" TextColor="Black"   FontSize="Small" />
                          </StackLayout>
                        </Grid>
                      </StackLayout>
                    </StackLayout>
                    <BoxView  HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HeightRequest="3"/>
                    <StackLayout.GestureRecognizers>
                      <TapGestureRecognizer Tapped="OnItemTapped" NumberOfTapsRequired="1" />
                    </StackLayout.GestureRecognizers>
                  </StackLayout>
                </ViewCell.View>
              </ViewCell>
            </DataTemplate>
          </ListView.ItemTemplate>
        </ListView>

BackEnd代码:On Image Tap我调用了以下功能。更新列表对象并将其提供给itemSource

public void ItemSelectionChanged(CachedImage source, StackLayout lstView)
        {
            var objClassId = "";
            if (source != null)
            {
                objClassId = source.ClassId;
            }
            else
            {
                objClassId = lstView.ClassId;
            }

            switch (Key)
            {
                case "LA":
                    if (objLstLeaveLst != null)
                    {
                        LeaveLst objtempLeaveLst = objLstLeaveLst.Find(s => s.TapId.ToString() == objClassId);
                        int index = objLstLeaveLst.IndexOf(objtempLeaveLst);

                        if (objLstLeaveLst[index].CheckSelect.ToString() == AppResources.ImgNotificationSelectionFalse)
                        {
                            objLstLeaveLst[index].CheckSelect = AppResources.ImgNotificationSelectionTrue;
                            List<bool> ImageSelectionFlag = objLstLeaveLst.Select(s => s.CheckSelect.ToString() == "check_sel.png").ToList();
                            ChangeSelectionImage(ImageSelectionFlag);
                        }
                        else
                        {
                            objLstLeaveLst[index].CheckSelect = AppResources.ImgNotificationSelectionFalse;
                            imgSelectAll.Source = "check_nor.png";
                            imgSelectAll.ClassId = "false";
                            lblSelectAll.ClassId = "false";
                        }

                        if (objLstLeaveLst[index].BgMainStackColor.Equals(Color.FromHex("#dddddd")))
                        {
                            objLstLeaveLst[index].BgMainStackColor = Color.FromHex("#f15a23");
                        }
                        else
                        {
                            objLstLeaveLst[index].BgMainStackColor = Color.FromHex("#dddddd");
                        }

                        lstLeaveNotificationDetails.ItemsSource = null;
                        lstLeaveNotificationDetails.ItemsSource = objLstLeaveLst;
                        if (Device.OS == TargetPlatform.iOS)
                        {
                            lstLeaveNotificationDetails.ScrollTo(objtempLeaveLst, ScrollToPosition.MakeVisible, false);
                        }
                    }
                    break;
}
}

为了解决这个问题,我把下面的代码

if (Device.OS == TargetPlatform.iOS)
                            {
                                lstLeaveNotificationDetails.ScrollTo(objtempLeaveLst, ScrollToPosition.MakeVisible, false);
                            }

但它没有给我一个合适的输出。如何在ios中保持滚动位置。请帮我在ios中渲染listView。我不想在更新项目源时滚动列表视图。

我也尝试了ObservableCollection,但我的GUI没有更新项目点击(图像点击和堆栈点击)。

2 个答案:

答案 0 :(得分:1)

iOS处理ListView及其ItemsSource更新的方式是更新ViewSource下的UITableView。在Xamarin.Forms或本机iOS上,将清除整个列表,并重新添加项目。

完成您尝试执行的操作的方法是使用ObservableCollection AND 为您的模型实施INotifyPropertyChanged

如果您的模型和您个人BindingContext的{​​{1}}更新了绑定到视图的属性,那么它将更新该单Cell而无需重新绑定整个列表。

此外,在UI上重新应用Cell是一个昂贵的过程,而更新单个单元格则很便宜!

以下是一个例子:

模特 -

ItemsSource

然后你的观点:

public class TodoItem : INotifyPropertyChanged
{
    private string _text;
    public string Text
    {
        get
        {
            return _text;
        }
        set
        {
            _text = value;
            PropertyChanged?.Invoke(new PropertyChangedEventArgs("Text"));
        }
    }
}

然后你的代码落后:

<ListView x:Name="MyListView" ItemsSource="{Binding TodoItems}">
    <ListView.ItemTemplate>
        <DataTemplate>
           <TextCell Text="{Binding Text}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

然后,您将看到正确的单元格更新文本字段,而无需更新任何其他项目,并保持滚动位置!

答案 1 :(得分:0)

使用listView.ScrollTo()方法,请参见下文:

 listView.ItemSelected += (sender, e) =>
            { 
     listView.ScrollTo(e.SelectedItem, ScrollToPosition.MakeVisible, false);               
};