Xamarin表单 - 多个DataTemplate ListView

时间:2016-06-29 16:32:32

标签: xaml xamarin.forms datatemplate

根据我之前的经验和网上的一些研究,我不知道是否有可能产生以下行为:

<ContentPage.Content>
  <AbsoluteLayout BackgroundColor="#2F767B">
    <AbsoluteLayout x:Name="ScreenLayoutAdapter" BackgroundColor="#235A5E"
                    AbsoluteLayout.LayoutFlags="All">
      <AbsoluteLayout.LayoutBounds>
        <OnPlatform x:TypeArguments="Rectangle" Android="0, 0, 1, 1" iOS="1, 1, 1, 0.975" WinPhone="0, 1, 1, 1"/>
      </AbsoluteLayout.LayoutBounds>

      <ListView x:Name="ListViewCourses" BackgroundColor="Transparent" RowHeight="90"
              AbsoluteLayout.LayoutBounds="0.5,1,0.9,0.9"
              AbsoluteLayout.LayoutFlags="All">
        <ListView.ItemTemplate>
          <DataTemplate>
            <ViewCell>
              <AbsoluteLayout Margin="2">

              <!-- Your design for the cell template -->

              </AbsoluteLayout>
            </ViewCell>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>

    </AbsoluteLayout>
  </AbsoluteLayout>
</ContentPage.Content>

在c#方面,我有一个ObservableCollection<Item>,我与ListViewCourses绑定。

但现在我的问题是:

当我触摸某个项目时,如何更改DataTemplate单​​元格?

我的意思是,它是一个项目列表,但当我触摸一个项目时,我希望该单元格长大并显示有关所选项目的更多信息。

如果我需要提供更多信息让你明白,请告诉我

提前感谢! :)

1 个答案:

答案 0 :(得分:2)

您可以执行的操作,而不是更改单个项目的DataTemplate,所有控件都包含您要显示的额外信息,设置为IsVisible = false,然后何时显示单击,在所有控件上设置IsVisible = true,并调用ListView.ForceLayout()以强制ViewCell重绘。

最后,请确保ListView.HasUnevenRows = trueViewCell不会改变大小。

或者,您可以在选择ViewCell时将包含额外信息的控件添加到ListView,它可能会更慢/更快,具体取决于ViewCell.ForceUpdateSize()中的项目数量,您要添加的额外控件的数量,以及是否需要查询数据库或服务以获取该额外信息。

如果您有任何疑问/问题,请与我们联系。

修改:实际上,您需要拨打ViewCell,信息here,以便在选择后更改ViewCell的尺寸。您还可能需要将ViewCell实例存储在类级变量中,以便在用户单击列表中的其他ListViewCachingStrategy.RecycleElement时将其缩小。

编辑#2:我遇到的最后一件事是,在iOS上,如果您在ListView上启用ViewCell,则很可能看不到{{1}中的任何更改在使控件可见并调用ForceUpdateSize()之后。这可能与最后一段here有关,但我不确定如何正确修复/绕过它。

编辑#3:例如,您可以执行以下操作:

<ViewCell>

     <!-- Use ListView.ItemTapped instead of the TapGestureRecognizer below -->
    <!-- <ViewCell.GestureRecognizers>
        <TapGestureRecognizer Tapped="OnViewCellTapped"/>
    </ViewCell.GestureRecognizers> -->
    <StackLayout>
        <!-- Main info displayed by default -->
        <StackLayout StyleId="DefaultStackLayout">
            <Label Text="{Binding ItemName}"/>
            <Label Text="{Binding ItemDates}"/>
            <Label Text="{Binding ItemCredits}"/>
        </StackLayout>

        <!-- Extra info displayed upon selection -->
        <StackLayout StyleId="ExtraStackLayout"
                     IsVisible="False">
            <Label Text="{Binding ItemBuilding}"/>
            <Label Text="{Binding ItemTeacher}"/>
            <Label Text="{Binding ItemHours}"/>
        </StackLayout>
    </StackLayout>
</ViewCell>

然后,当用户选择单元格时,您需要执行以下操作:

using System.Linq;

...

private void OnViewCellTapped(object sender, EventArgs args) {}
    tapCount++;
    ViewCell viewCellSender = (ViewCell)sender;

    StackLayout rootStack = (StackLayout)viewCellSender.View;

    StackLayout extraInfoStack = rootStack.Children.Where(stack => stack.StyleId == "ExtraStackLayout");
    extraInfoStack.IsVisible = true;

    viewCellSender.ForceUpdateSize();
}

我之前没有测试任何内容,甚至没有尝试过,所以如果上述方法不起作用,我相信在点击extraInfoStack后插入ViewCell元素内容会有效。但首先尝试上面的尝试。显然,如果要使用AbsoluteLayout,则需要更改布局,并且还需要更改OnViewCellTapped()投射代码。

编辑#4:如果可能的话,我通常会尝试避开高度和宽度值的常数,但有时这是不可避免的。因此,为了使这一切正常工作,您将不得不设置ListView.HasUnevenRows = true,这意味着您需要完全摆脱ListView.RowHeight值,因为需要允许行具有可变高度。

如果可能的话,我会尝试不设置常量高度值,但是如果你没有将高度设置为常量值就绝对无法生存,那么你可以给你的ViewCell&#39; s内部AbsoluteLayout一个HeightRequest为120,但是在选择项目后,您需要更改该值,此时您可以看到额外的控件并且在调用ViewCell.ForceUpdateSize()之前。将IsVisible设置为false应该使控件不占用任何空间,因此这些额外的控件不应该在隐藏时调整大小,但我自己从未尝试过。

如果您遇到问题,请告诉我。