【问题标题】:How to set default value to false when using converter with Label's visibility Xamarin forms将转换器与 Label 的可见性 Xamarin 表单一起使用时如何将默认值设置为 false
【发布时间】:2021-11-14 23:26:46
【问题描述】:

我正在使用带有LabelIsVisible 属性的转换器。

<Label IsVisible="{Binding products, Converter={StaticResource EmptyCollectionToBoolConverter}}" Text="No data found">  

如果products 为空EmptyCollectionToBoolConverter 返回true 否则false。首次加载屏幕时,“未找到数据”消息显示几秒钟,然后数据正在加载。

我想修复它,只有当products 为空时才需要显示标签。我该怎么做?

【问题讨论】:

    标签: xaml xamarin xamarin.forms converters


    【解决方案1】:

    您可以在后面的代码中覆盖IsVisible 值。

    <Label x:Name="MyLabel" IsVisible="{Binding products, Converter={StaticResource EmptyCollectionToBoolConverter}}" Text="No data found">
    

    后面的代码

    // probably ctor
    MyLabel.IsVisible = false;
    

    第二个选项可以是使用DataTrigger

    <Label Text="No data found" IsVisible="false">
        <Label.Triggers>
            <DataTrigger TargetType="Label" Binding="{Binding products, Converter={StaticResource EmptyCollectionToBoolConverter}}" Value="True">
                <Setter Property="IsVisible" Value="True" />
            </DataTrigger>
        </Label.Triggers>
    </Label>
    

    【讨论】:

    • 嗨,我试过了,两种解决方案都不起作用..
    【解决方案2】:

    如果您使用的是 CollectionView,则可以使用 EmptyView ,当集合为空时,它将显示您在该 XAML 中放入的任何内容。

    或者你可以实现bindablelayout,它也实现了emptyViewTemplate。

    否则您将不得不创建另一个绑定或另一个转换器。

    类似 public bool MyBinding{get=&gt; myList!=null | myList.Count != | isLoadingFlag } 的东西。但是如果你修改你的集合,你将不得不调用 propertychanged 事件

    【讨论】:

    • 不使用collectionview..
    • 当您的应用程序启动时,通常集合将为空。这就是为什么您会在几分之一秒内显示标签。为了防止这种情况,您必须先加载集合。或者,您可以使用绑定到 bool 属性,如果集合为空且未加载数据,则该属性返回 true
    • 类似 public bool MyBinding{get=&gt; myList!=null | myList.Count != | isLoadingFlag } 的东西。但是如果你修改你的集合,你将不得不调用 propertychanged 事件
    【解决方案3】:

    我不确定这是否是您的问题,但我会检查几件事:

    1. 您可以不在 XAML 中设置绑定,而是在加载数据后的代码中设置。
    2. 您可能需要将 BindingContext 设置为 products(如果尚未这样做的话)。
    3. 另外,最好将标签的绑定路径设置为集合的Count 属性。
    4. 最后,在 XAML 中将 IsVisible 设置为 false(默认)。此硬代码将被加载数据时设置的绑定覆盖。

    无论如何,我制定了一个完成这项工作的最小完整工作示例。

    它的基本工作方式如下:应用程序启动并没有显示任何内容......然后继续加载数据。加载数据时出现标签,显示集合中的项目数。 工具栏中还有两个按钮:添加项目删除项目。如果您删除所有项目,则会出现No data found 标签。

    查看代码中的 cmets

    Page1.xaml.cs

    using System;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.Threading.Tasks;
    
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    
    namespace scrollviewPrompt
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class Page1 : ContentPage
        {
            // products is an observable collection so that 
            // it notifies when it changes.
            public ObservableCollection<string> products { get; set; }
    
            public Page1()
            {
                InitializeComponent();
            }
    
            protected override async void OnAppearing()
            {
                // Initialize your products collection
                products = new ObservableCollection<string>();
    
                // Set binding context of the whole Page1 
                // to your products collection
                BindingContext = products;
    
                // Load data asynchronously.
                // At this point the data is already bound to 
                // our collection, so when data is loaded 
                // "No data found" label will dissapear.
                await LoadDataAsync();
    
                base.OnAppearing();
    
            }
    
    
            private async Task LoadDataAsync()
            {
    
                await Task.Delay(4000);
    
                products.Add("Toks");
    
                noDataLabel.SetBinding(Label.IsVisibleProperty, new Binding()
                {
                    Path="Count",
                    Converter = new EmptyCollectionToBoolConverter()
                });
    
            }
    
    
            // Add items to collection.
            private void AddClicked(object sender, EventArgs e)
            {
                products.Add("locs");
            }
    
            // If collection not empty, remove first item.
            private void RemoveClicked(object sender, EventArgs e)
            {
                if (products.Count>0)
                    products.RemoveAt(0);
            }
        }
    
        public class EmptyCollectionToBoolConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var count = (int)value;
    
                return count==0;
    
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
    
        public class Not_EmptyCollectionToBoolConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                var count = (int)value;
    
                return count > 0;
    
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
    }
    

    Page1.xaml

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:scrollviewPrompt"
                 x:Class="scrollviewPrompt.Page1">
        
        <ContentPage.Resources>
            <ResourceDictionary>
                <local:EmptyCollectionToBoolConverter x:Key="EmptyCollectionToBoolConverter"/>
                <local:Not_EmptyCollectionToBoolConverter x:Key="Not_EmptyCollectionToBoolConverter"/>
            </ResourceDictionary>
        </ContentPage.Resources>
    
        <ContentPage.ToolbarItems>
            <ToolbarItem Text="Add Item"
                         Clicked="AddClicked"/>
            <ToolbarItem Text="Remove Item"
                         Clicked="RemoveClicked"/>
        </ContentPage.ToolbarItems>
        
        <ContentPage.Content>
            
            
            
            <StackLayout>
                <!--No data found is bound to Count property of BindingContext (products). 
                    when products change, Count changes and IsVisible is updated.-->
                <Label x:Name="noDataLabel" 
                       Text="No data found"
                       IsVisible="false"
                       VerticalOptions="CenterAndExpand" 
                       HorizontalOptions="CenterAndExpand" />
                <Label Text="{Binding Path=Count, StringFormat='{0} items'}"
                       IsVisible="{Binding Path=Count, Converter={StaticResource Not_EmptyCollectionToBoolConverter}}"
                       VerticalOptions="CenterAndExpand" 
                       HorizontalOptions="CenterAndExpand" />
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>
    

    【讨论】:

      【解决方案4】:

      考虑使用binding fallbacks,它允许您在未设置绑定上下文或绑定目标为空时指定“默认”值。

      <Label IsVisible="{Binding products, Converter={StaticResource EmptyCollectionToBoolConverter}, FallbackValue='False', TargetNullValue='False'}" Text="No data found">  
      

      您可能不需要两者,但它将确保始终隐藏标签,直到可以解析绑定上下文 (ViewModel) 并且绑定目标 (products) 不为空,因此转换器可以正确评估是否显示标签。

      【讨论】:

        猜你喜欢
        • 2018-08-17
        • 1970-01-01
        • 1970-01-01
        • 2013-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多