问题描述
我有一个宠物的集合视图。带有图像和名称。当您单击名称时,它会启用扩展器,您可以查看宠物的详细信息。这适用于一个回撤。自然地,当扩展器扩展时,它会占用空间!扩展它占用的空间只是空白,是否可以摆脱这个空间?
我的收藏视图:
<CollectionView x:Name="PetCollection" ItemsSource="{Binding EmptyPetInfo}" Margin="65,10,0" HeightRequest="400">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid x:Name="PetCollectionGrid" Padding="0" ColumnDeFinitions="140,140" >
<Grid.RowDeFinitions>
<RowDeFinition Height = "140"/>
<RowDeFinition Height = "5"/>
<RowDeFinition Height = "20*"/>
</Grid.RowDeFinitions>
<xct:AvatarView Source="{Binding imageUrl}"
VerticalOptions="Center"
HorizontalOptions="Center"
Size="100"
CornerRadius="50"
Aspect="AspectFill">
</xct:AvatarView>
<BoxView Color="Gray"
HeightRequest="2"
HorizontalOptions="Fill" Grid.Row="1" />
<xct:Expander Grid.Row="2" Tapped="Expander_Tapped">
<xct:Expander.Header>
<Label Text="{Binding PetName}"
HorizontalTextAlignment="Center"/>
</xct:Expander.Header>
<Grid RowDeFinitions="20*,20*,20*">
<Label Text="{Binding Breed}"/>
<Label Text="{Binding dob}" Grid.Row="1"/>
<Label Text="{Binding Gender}" Grid.Row="2"/>
<Label Text="{Binding Weight}" Grid.Row="3"/>
</Grid>
</xct:Expander>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
所以我在扩展器中添加了这个代码。然而,这只适用于最后一行的扩展器。当它扩展时,它会占用空间,而当它关闭时,空间就会消失。中间和顶部的扩展器在扩展时会占用空间,但当它们关闭时仍然留下空白。
private void Expander_Tapped(object sender,EventArgs e)
{
Expander Expander = sender as Expander;
Grid grid = (Grid)Expander.Parent;
int index = Grid.GetRow(Expander);
RowDeFinition rowdef = grid.RowDeFinitions[index];
if (Expander.IsEnabled)
{
rowdef.Height = new GridLength(1,Expander.IsExpanded ? GridUnitType.Star : GridUnitType.Auto);
}
else
{
rowdef.Height = new GridLength(0,!Expander.IsExpanded ? GridUnitType.Absolute : GridUnitType.Absolute);
}
}
解决方法
Expander doc 表示 “已知 Expander 控件在 ListView 或 CollectionView 中使用时会显示不需要的行为。目前我们建议不要在这些控件之一中使用 Expander。” .
一种可能的解决方法是“替换”绑定集合中的项目,强制重新绘制布局。
可能还有其他方法可以强制重绘该项目。
,目前在集合视图中使用扩展器会给你带来各种麻烦。我使用的一种解决方法是使用具有可绑定布局的 stacklayout 或 grid 之类的容器来替换 collectionview。 如果您的收藏品数量有限,这非常有效。如果您有大量收藏,这不是一个好的选择,您应该考虑更改设计以不使用扩展器。
https://devblogs.microsoft.com/xamarin/xamarin-forms-bindable-layout/
,我能够使用您提供的代码重现此问题。当您向上滚动 AB 行时,它将删除空白。
一种简单的方法是使用 RefreshView
刷新页面。绑定 IsRefreshing 属性来控制刷新。
XML:
<RefreshView IsRefreshing="{Binding isRefreshing}">
<CollectionView x:Name="PetCollection" ItemsSource="{Binding EmptyPetInfo}" Margin="65,10,0" HeightRequest="400">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid x:Name="PetCollectionGrid" ColumnDefinitions="140,140" >
<Grid.RowDefinitions>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
</Grid.RowDefinitions>
<xct:AvatarView Source="{Binding imageUrl}"
VerticalOptions="Center"
HorizontalOptions="Center"
Size="100"
CornerRadius="50"
Aspect="AspectFill">
</xct:AvatarView>
<BoxView Color="Gray"
HeightRequest="2"
HorizontalOptions="Fill" Grid.Row="1" />
<xct:Expander Grid.Row="2" Tapped="Expander_Tapped" >
<xct:Expander.Header>
<Label Text="{Binding PetName}"
HorizontalTextAlignment="Center"/>
</xct:Expander.Header>
<Grid RowDefinitions="20*,20*,20*">
<Label Text="{Binding Breed}"/>
<Label Text="{Binding DOB}" Grid.Row="1"/>
<Label Text="{Binding Gender}" Grid.Row="2"/>
<Label Text="{Binding Weight}" Grid.Row="3"/>
</Grid>
</xct:Expander>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
背后的代码:
public partial class MainPage : ContentPage
{
public ObservableCollection<PetInfo> EmptyPetInfo { get; set; }
public bool isRefreshing { get; set; }
public MainPage()
{
InitializeComponent();
isRefreshing = false;
EmptyPetInfo = new ObservableCollection<PetInfo>()
{
new PetInfo(){ Breed="Breed1",DOB="DOB1",Gender="F",PetName="A",Weight="1",imageUrl="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"},new PetInfo(){ Breed="Breed2",DOB="DOB2",Gender="M",PetName="B",Weight="2",new PetInfo(){ Breed="Breed3",DOB="DOB3",PetName="C",Weight="13",new PetInfo(){ Breed="Breed4",DOB="DOB4",PetName="D",Weight="14",new PetInfo(){ Breed="Breed5",DOB="DOB5",PetName="E",new PetInfo(){ Breed="Breed6",DOB="DOB6",PetName="F",Weight="15",new PetInfo(){ Breed="Breed7",DOB="DOB7",PetName="G",Weight="12",new PetInfo(){ Breed="Breed8",DOB="DOB8",PetName="H",Weight="61",new PetInfo(){ Breed="Breed9",DOB="DOB9",PetName="I",Weight="16",new PetInfo(){ Breed="Breed10",DOB="DO010",PetName="J",new PetInfo(){ Breed="Breed11",DOB="DOB11",PetName="K",Weight="11",imageUrl="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Papio_anubis_%28Serengeti%2C_2009%29.jpg/200px-Papio_anubis_%28Serengeti%2C_2009%29.jpg"}
};
this.BindingContext = this;
}
private void Expander_Tapped(object sender,EventArgs e)
{
Expander Expander = sender as Expander;
if (!Expander.IsExpanded)
{
isRefreshing = true;
}
}
}
public class PetInfo
{
public string imageUrl { get; set; }
public string PetName { get; set; }
public string Breed { get; set; }
public string DOB { get; set; }
public string Gender { get; set; }
public string Weight { get; set; }
}