将转换器与 Label 的可见性 Xamarin 表单一起使用时如何将默认值设置为 false
Posted
技术标签:
【中文标题】将转换器与 Label 的可见性 Xamarin 表单一起使用时如何将默认值设置为 false【英文标题】:How to set default value to false when using converter with Label's visibility Xamarin forms 【发布时间】:2021-11-14 23:26:46 【问题描述】:我正在使用带有Label
的IsVisible
属性的转换器。
<Label IsVisible="Binding products, Converter=StaticResource EmptyCollectionToBoolConverter" Text="No data found">
如果products
为空EmptyCollectionToBoolConverter
返回true
否则false
。首次加载屏幕时,“未找到数据”消息显示几秒钟,然后数据正在加载。
我想修复它,只有当products
为空时才需要显示标签。我该怎么做?
【问题讨论】:
【参考方案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 MyBindingget=> myList!=null | myList.Count != | isLoadingFlag
的东西。但是如果你修改你的集合,你将不得不调用 propertychanged 事件
【讨论】:
不使用collectionview.. 当您的应用程序启动时,通常集合将为空。这就是为什么您会在几分之一秒内显示标签。为了防止这种情况,您必须先加载集合。或者,您可以使用绑定到 bool 属性,如果集合为空且未加载数据,则该属性返回 true 类似public bool MyBindingget=> myList!=null | myList.Count != | isLoadingFlag
的东西。但是如果你修改你的集合,你将不得不调用 propertychanged 事件【参考方案3】:
我不确定这是否是您的问题,但我会检查几件事:
-
您可以不在 XAML 中设置绑定,而是在加载数据后的代码中设置。
您可能需要将 BindingContext 设置为
products
(如果尚未这样做的话)。
另外,最好将标签的绑定路径设置为集合的Count
属性。
最后,在 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
) 不为空,因此转换器可以正确评估是否显示标签。
【讨论】:
以上是关于将转换器与 Label 的可见性 Xamarin 表单一起使用时如何将默认值设置为 false的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin 表单:如何处理 flowlistview 所选项目的可见性?
Xamarin:Java 绑定项目 - 无法更改本地界面的可见性