【问题标题】:Xamarin Forms - Multiple DataTemplate ListViewXamarin 表单 - 多个 DataTemplate ListView
【发布时间】:2016-06-29 16:32:32
【问题描述】:

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

<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&lt;Item&gt;,我与 ListViewCourses 绑定。

但现在我的问题是:

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

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

如果我必须提供更多信息以使您理解,请告诉我

提前致谢! :)

【问题讨论】:

    标签: xaml xamarin.forms datatemplate


    【解决方案1】:

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

    最后,确保ListView.HasUnevenRows = true 否则ViewCell 不会改变大小。

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

    如果您有任何问题/问题,请告诉我。

    编辑:实际上,您将需要调用ViewCell.ForceUpdateSize(),信息here,以便在选择后更改ViewCell 的大小。您可能还需要将该 ViewCell 实例存储在类级别变量中,以便在用户单击列表中的不同 ViewCell 时将其缩小。

    编辑#2:我遇到的最后一件事是,在 iOS 上,如果您在 ListView 上启用了 ListViewCachingStrategy.RecycleElement,则在使控件可见后,您很可能不会在 ViewCell 中看到任何变化并致电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();
    }
    

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

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

    如果可能的话,我会尽量不设置常量高度值,但如果你绝对不能不将高度设置为常量值,那么你可以给你的ViewCell 的内部AbsoluteLayout 一个HeightRequest 共 120 个,但是您需要在选择项目时更改该值,在使您的额外控件可见之后和调用 ViewCell.ForceUpdateSize() 之前。将IsVisible 设置为false 应该是为了使控件不占用任何空间,因此这些额外的控件在隐藏时不应该与大小混淆,但我自己从未尝试过。

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

    【讨论】:

    • 感谢您的回答 :) 所以您的意思是我必须在 datatemplate xaml 中创建 两个主要布局ViewCell 中,然后只创建一个当时Visible?
    • 好吧,老实说,这个答案太完美了,谢谢!!我想象它真的更难......&lt;TapGestureRecognizer Tapped="OnViewCellTapped"/&gt;作为监听器......我想为每个项目添加一个监听器......当我看到你的代码时真是个白痴;)正如你所说,是的,我需要更新@ 987654358@,但此刻我想到一个问题,您如何处理ListViewcell 的大小调整?我的意思是我的定义是Rows.Height="120"
    • @Emixam23 很高兴它很有帮助,我之前没有看到。我假设您指的是您设置的ListView.RowHeight 值?如果是这样,请参阅编辑#4(在 cmets 中没有足够的空间)。现在您提到它,您应该使用ListView.ItemTapped 而不是TapGestureRecognizer,它们的行为或多或少是相同的。没有正确思考。我编辑了我的答案。
    • 第一,一如既往地感谢 x) 第二,我必须处理这个固定尺寸的设计......但是,我只处理比例值! 第三,我无法驾驭 C# 部分,Content 不存在,Children 也是:/ 如果我理解,View 可以代替 Content,你怎么看? #EDIT ARRRGG 它不起作用,我无法弄清楚 >
    • 嗨,你看到我的评论了吗? :) @hvaughan3
    猜你喜欢
    • 2018-03-11
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    相关资源
    最近更新 更多