我正在研究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没有更新项目点击(图像点击和堆栈点击)。
答案 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);
};