【问题标题】:Dynamically show/hide Header or Footer of Xamarin.Forms.ListView动态显示/隐藏 Xamarin.Forms.ListView 的页眉或页脚
【发布时间】:2017-06-13 04:49:37
【问题描述】:

有没有办法在运行时根据条件动态显示/隐藏 ListView 的标题。

<ListView x:Name="ListViewChallenges" Header="{Binding .}">

    <ListView.FooterTemplate>
        <DataTemplate>
            <Label Text="No Elements found." IsVisible="{Binding FooterIsVisible}" />
        </DataTemplate>
    </ListView.FooterTemplate>

    <!-- ... -->

</ListView>

在 BindingContext 中,我声明了 FooterIsVisible 属性。当它为假时,页脚应该是不可见的。但是这不起作用,页脚总是为 ListView 底部的标签占用一定的空间。

这有可能吗?

【问题讨论】:

    标签: listview xamarin xamarin.forms


    【解决方案1】:

    您应该能够隐藏页脚而不让它占用任何空间。我相信您需要为FooterTemplate 中的标签设置HeightRequest。你可以这样做:

    <Label Text="No Elements found." IsVisible="{Binding FooterIsVisible}">
        <Label.Triggers>
            <Trigger TargetType="Label" Property="IsVisible" Value="False">
                <Setter Property="HeightRequest" Value="0" />
            </Trigger>
        </Label.Triggers>
    </Label>
    

    【讨论】:

    • 我之前尝试过HeightRequest,但它不起作用。 Footer 忽略它并仍然占用该空间,即使在父 ContentView 上触发 ForceLayout。
    • 您使用的是 iOS、Android 还是其他设备?我刚刚在 Android 上对这段代码进行了快速测试,打开和关闭了 FooterIsVisible,据我所知,它似乎可以工作。我目前无法访问我的 Mac,因此无法在 iOS 上查看。
    • 感谢您的检查。我确实在 iOS 和 Android 上再次尝试过,你适合 Android。它在那里工作,所以问题只存在于iOS上。一旦页脚可见,即使不可见,它仍会占用相同的空间。那可能是一个错误。我的印象是 Xamarin 并没有真正对“较小”的问题做出反应 - 所以我想我必须忍受它。
    • 我将此作为错误提交:bugzilla.xamarin.com/show_bug.cgi?id=51961
    【解决方案2】:

    您应该使用 FooterTemplate 和 Footer 属性。它作为 ItemTemplate 和 ItemSource:

    <ListView Footer="{Binding IsFooterVisible}">
        <ListView.FooterTemplate>
            <DataTemplate>
                <!-- Footer content. Always visible -->
            </DataTemplate>
        <ListView.FooterTemplate>
    </ListView>
    

    并绑定到页脚属性一些可以为空的东西(例如对象)。或者你可以使用转换器来转换:true -> new object() and false -> null

    还可以创建 ListView 的子类。我的例子(IsLoading 属性就是你要搜索的):

    Xaml:

    <?xml version="1.0" encoding="UTF-8"?>
    <ListView xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        x:Class="Panor.Views.LoadableListView"
        x:Name="element"
        >
        <ListView.FooterTemplate>
            <DataTemplate>
                <ContentView>
                    <ActivityIndicator IsRunning="true"
                        Margin="0, 5"
                        Color="{StaticResource mainColor}"
                        VerticalOptions="CenterAndExpand"
                        HorizontalOptions="CenterAndExpand"
                        >
                        <ActivityIndicator.Scale>
                            <OnPlatform x:TypeArguments="x:Double" iOS="2" Android="1" />
                        </ActivityIndicator.Scale>
                    </ActivityIndicator>
                </ContentView>            
            </DataTemplate>
        </ListView.FooterTemplate>
    </ListView>
    

    代码隐藏:

    public partial class LoadableListView : ListView
    {
        public LoadableListView()
        {
            InitializeComponent();
    
            this.ItemAppearing += OnItemAppearing;
        }
    
        public static readonly BindableProperty IsLoadingProperty = BindableProperty.Create(
            nameof(IsLoading),
            typeof(bool),
            typeof(LoadableListView),
            false,
            propertyChanged: (bindable, oldValue, newValue) => 
            {
                var element = (LoadableListView)bindable;
    
                element.Footer = (bool)newValue ? new object() : null;
            }
        );
        public bool IsLoading
        {
            set => SetValue(IsLoadingProperty, value);
            get => (bool)GetValue(IsLoadingProperty);
        }
    
        public static readonly BindableProperty ScrolledDownCommandProperty = BindableProperty.Create(
            nameof(ScrolledDownCommand),
            typeof(ICommand),
            typeof(LoadableListView)
        );
        public ICommand ScrolledDownCommand
        {
            set => SetValue(ScrolledDownCommandProperty, value);
            get => (ICommand)GetValue(ScrolledDownCommandProperty);
        }
    
        void OnItemAppearing(object sender, ItemVisibilityEventArgs e)
        {
            if (ItemsSource == null) return;
            if (ScrolledDownCommand == null) return;
    
            object last = null;
    
            if (ItemsSource is IList)
            {
                var length = (ItemsSource as IList).Count;
                last = (ItemsSource as IList)[length - 1];
            }
            else 
            {
                foreach (var item in ItemsSource)
                    last = item;
            }
    
            if (e.Item == last && ScrolledDownCommand.CanExecute(null))
                ScrolledDownCommand.Execute(null);
    
        }
    

    消费:

     <views:LoadableListView ItemsSource="{Binding ItemSource}"
                    RowHeight="120"
                    SeparatorColor="#c7c8c9" 
                    IsLoading="{Binding IsMoreLoading}"
                    ScrolledDownCommand="{Binding ScrolledDownCommand}"
                    IsPullToRefreshEnabled="true"
                    IsRefreshing="{Binding IsRefreshing}"
                    RefreshCommand="{Binding RefreshCommand}"
                    >
                    <views:LoadableListView.ItemTemplate>
                        <DataTemplate>
                            <cells:MagazinesListCell Name="{Binding Name}" 
                                Publisher="{Binding Publisher}"
                                Price="{Binding Price}"
                                Image="{Binding Converter={StaticResource UriToImageSourceConvertor}, Path=Image}"
                                Commands="{Binding Commands}"
                                />
                        </DataTemplate>
                    </views:LoadableListView.ItemTemplate>
                </views:LoadableListView>
    

    【讨论】:

      【解决方案3】:

      如果你想隐藏页脚,因为列表视图是空的,只需设置

      listview.footer = null
      

      【讨论】:

        【解决方案4】:

        您可以将您的页脚模板包装在ViewCell 中,然后在您不想显示时将ViewCellHeight 设置为0。如果这样做,请确保将ListView.HasUnevenRows 属性设置为True

        <ListView x:Name="ListViewChallenges" Header="{Binding .}" HasUnevenRows="True">
        
            <ListView.FooterTemplate>
                <DataTemplate>
                    <ViewCell Height={Binding FooterHeight}>
                        <Label Text="No Elements found." IsVisible="{Binding FooterIsVisible}" />  
                    </ViewCell>
                </DataTemplate>
            </ListView.FooterTemplate>
        
        <!-- ... -->
        
        </ListView>
        

        【讨论】:

        • 如果使用 ViewCell 我得到 System.ArgumentException: Value was an invalid value for FooterTemplate
        【解决方案5】:

        解决办法如下:

        <ListView.FooterTemplate>
          <DataTemplate>
        
            <!--VIEW-->
            <ActivityIndicator IsRunning="true" IsVisible="{Binding IsLoadingOnDemand}" HorizontalOptions="CenterAndExpand" Margin="15">
              <ActivityIndicator.Triggers>
                <Trigger TargetType="ActivityIndicator" Property="IsVisible" Value="False">
                  <Setter Property="HeightRequest" Value="0" />
                </Trigger>
              </ActivityIndicator.Triggers>
            </ActivityIndicator>
        
          </DataTemplate>
        </ListView.FooterTemplate>

        【讨论】:

          【解决方案6】:

          这适用于我没有 tmlpate(如果您需要从父 .cs 代码的标题中引用元素,则模板将不起作用)。因此必须使用 0 而不是 0 高度的容器并切换它们的可见性。

            <ListView.Header>
          <StackLayout Style="{StaticResource DefaultStackLayout}">
              <StackLayout x:Name="ZeroHeaderContainer"
                           HeightRequest="0"
                           IsVisible="{Binding SomeBooleanField}"/>
          
          
              <StackLayout  x:Name="NormalHeaderContainer"
                       Style="{StaticResource DefaultStackLayout}"
                       HorizontalOptions="Fill" 
                       IsVisible="{Binding SomeBooleanField,Converter={StaticResource InverseBooleanConverter}}">
              </StackLayout>
          </StackLayout>      
          

          【讨论】:

            【解决方案7】:

            我尝试了所有变体:
            1)Header属性绑定new object()null
            2) 两个没有转换器的堆栈布局 (https://stackoverflow.com/a/53197844/7429947)
            3) DataTriggerTrigger 更改 IsVisible 设置 HeightRequest

            这对我没有帮助,然后我在“HeightRequest”上替换了MinimumHeightRequest,第二个变体对 iOS 和 Android 有帮助!

            Xamarin.Forms 版本:4.6.0.726

            【讨论】:

            • 欢迎来到 StackOverflow,如果需要理解答案,请添加更多描述和代码,因为它会尽快解决其他人的问题
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-29
            • 2018-10-22
            • 1970-01-01
            • 2016-03-06
            • 1970-01-01
            • 2018-07-26
            相关资源
            最近更新 更多