Xamarin Forms - 否定 bool 绑定值

问题描述 投票:0回答:5

我正在学习 xamarin 形式和 mvvm 模式。我想知道是否可以否定绑定布尔值。我的意思是:

我有,比方说,带有

isVisible
绑定的条目:

<Entry
    x:Name="TextEntry"
    IsVisible="{Binding IsVisibleEntry}"
/>

Label
TextEntry
可见时我想隐藏它们。

<!--  ofc it is not working -->
<Label
    x:Name="MainLabel" 
    isVisible="!{Binding IsVisibleEntry}"
/>

是否可以在

MainLabel
中不为
ViewModel
创建新变量?

c# xamarin mvvm xamarin.forms
5个回答
94
投票

选项一:转换器

定义转换器:

    public class InverseBoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return !((bool)value);
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
            //throw new NotImplementedException();
        }
    }

XAML 中的用法:

    <Label x:Name="MainLabel" 
           isVisible="{Binding IsVisibleEntry, Converter={Helpers:InverseBoolConverter}}"/>

XAML 标头

    xmlns:Helpers="clr-namespace:HikePOS.Helpers"

选项二:触发

    <Label x:Name="MainLabel" isVisible="{Binding IsVisibleEntry}">
        <Label.Triggers>
            <DataTrigger TargetType="Label" Binding="{Binding IsVisibleEntry}" Value="True">
                <Setter Property="IsVisible" Value="False" />
            </DataTrigger>
        </Label.Triggers>
    </Label>

18
投票

您可以使用 Xamarin Community Toolkit,而不是编写自己的转换器,它现在有一个可以开箱即用的转换器 invertedboolconverter。这个例子(取自微软的文档)展示了它是如何工作的:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
             x:Class="MyLittleApp.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <xct:InvertedBoolConverter x:Key="InvertedBoolConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>

        <Label IsVisible="{Binding MyBooleanValue, Converter={StaticResource InvertedBoolConverter}}" />

    </StackLayout>
</ContentPage>

13
投票

您将需要创建一个反向转换器,以便您的绑定看起来有点像这样:

public class InverseBoolConverter : IValueConverter
{
    public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !(bool)value;
    }
    public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !(bool)value;
    }
}

在您的 XAML 中

<local:InverseBoolConverter x:Key="inverter"/>
<Entry
x:Name="TextEntry"
IsVisible="{Binding IsVisibleEntry, Converter={StaticResource inverter}}"
/>

2
投票

尽管@praty 的解决方案有效,但如果您像我一样使用自定义控件/视图或 XCT 的弹出窗口。在我们的 XAML 中使用转换器之前,我们需要这样指定:

<ContentView.Resources>
    <converters:InverseBoolConverter x:Key="invrerseBoolConverter" />
</ContentView.Resources>

因此最终代码将是:

InverseBoolConverter.cs

// Under namespace MyProject.Converters

public class InverseBoolConverter : IValueConverter
{
    public object Convert (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !(bool)value;
    }
    public object ConvertBack (object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !(bool)value;
    }
}

XAML 代码

<xct:Popup ...
           xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
           xmlns:converters="clr-namespace:MyProject.Converters"
           ...>

    <ContentView>
        <ContentView.Resources>
            <converters:InverseBoolConverter x:Key="inverseBoolConverter" />
        </ContentView.Resources>

        <StackLayout>
            <Label IsVisible="{Binding IsVisibleLabel, Converter={StaticResource inverseBoolConverter}}" />
        </StackLayout>
    </ContentView>
</xct:Popup>

注意:虽然我们可以使用 Xamarin 社区工具包的 InvertedBoolConverter,但我已经描述了手动解决方案,以便我们可以添加除内置转换器之外的自定义值转换器。


2
投票

我喜欢已经提供的答案,但我想我应该添加我自己有时使用的版本。在 MVVM 架构中,视图模型的属性都在对象设置器中调用

SetProperty()
,从而引发
INotifyPropertyChanged
事件。我一直在做的是将第二个属性添加到视图模型中,并在第一个属性的设置器中将其值设置为
!value

例如,每当属性

button.IsEnabled = false
出现时,我希望按钮为
ViewModel.IsBusy = true
。这是一个反向布尔示例,就像您所问的那样。

ViewModel.cs 属性:

private bool enableButton;
public bool EnableButton
{
    get { return enableButton; }
    set { SetProperty(ref enableButton, value); }
}
private bool isBusy;
bool IsBusy
{
    get { return isBusy; }
    set
    {
        SetProperty(ref isBusy, value);
        EnableButton = !value;
    }
}

XAML:

<ActivityIndicator IsRunning="{Binding IsBusy}"/>

<Button Text="Start Sync"
        Command="{Binding SyncCommand}"
        IsEnabled="{Binding EnableButton}"/>

这样,在我的代码中任何时候我调用

IsBusy = true
,它都会同时设置
button.IsEnabled = false
,解决反向布尔问题。

© www.soinside.com 2019 - 2024. All rights reserved.