如何在WPF中绑定反向布尔属性?

441
我手头有一个对象,其中包含一个IsReadOnly属性。如果这个属性为true,我想将一个Button的IsEnabled属性(例如)设置为false。我本来以为可以像这样轻松地实现:IsEnabled="{Binding Path=!IsReadOnly}",但在WPF中行不通。难道我必须遍历所有的样式设置吗?这对于只需将一个布尔值设置为另一个布尔值的反向值来说,似乎过于冗长。
<Button.Style>
    <Style TargetType="{x:Type Button}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="True">
                <Setter Property="IsEnabled" Value="False" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=IsReadOnly}" Value="False">
                <Setter Property="IsEnabled" Value="True" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Button.Style>

相关:https://dev59.com/y3RB5IYBdhLWcg3wuZbo - StayOnTarget
1
Eh MS 做了好事情,但是没有完整完成。 - user1005462
16个回答

2

在参考@Paul的答案后,我在ViewModel中编写了以下内容:

public bool ShowAtView { get; set; }
public bool InvShowAtView { get { return !ShowAtView; } }

我希望在这里放一个片段,能够帮助一些人,尤其是像我这样的新手。
如果有错误,请告诉我!

顺便说一下,我也同意@heltonbiker的评论-只有在不需要使用它超过3次时,这绝对是正确的方法...


2
由于不是完整的属性且缺少"OnPropertyChanged",这无法工作。根据情况,我将使用第一或第二种答案。除非您使用类似Prism框架这样的框架,其中框架知道何时更新“引用”属性。然后,在使用像您建议的内容(但包含完整属性)和答案1之间进行选择。 - Oyiwai

1
我做了类似的事情。我在后台创建了一个属性,只有在下拉框完成数据搜索后才能选择它。当我的窗口首次出现时,它会启动一个异步加载命令,但我不希望用户在它仍在加载数据时点击下拉框(它将为空,然后将被填充)。因此,默认情况下该属性为false,所以在getter中返回反向值。然后当我正在搜索时,我将属性设置为true,并在完成后设置回false。
private bool _isSearching;
public bool IsSearching
{
    get { return !_isSearching; }
    set
    {
        if(_isSearching != value)
        {
            _isSearching = value;
            OnPropertyChanged("IsSearching");
        }
    }
}

public CityViewModel()
{
    LoadedCommand = new DelegateCommandAsync(LoadCity, LoadCanExecute);
}

private async Task LoadCity(object pArg)
{
    IsSearching = true;

    //**Do your searching task here**

    IsSearching = false;
}

private bool LoadCanExecute(object pArg)
{
    return IsSearching;
}

然后对于下拉框,我可以直接将其绑定到IsSearching:
<ComboBox ItemsSource="{Binding Cities}" IsEnabled="{Binding IsSearching}" DisplayMemberPath="City" />

0

类似于jevansio的答案,实现了一个名为BindableBool的类,该类具有IsTrue和IsFalse属性,我可以将这两个交替组件的IsVisible绑定到这些属性。

Github: https://github.com/balintn22/BindableBool

Nuget: YA.BindableBool


0

我使用类似@Ofaim的方法

private bool jobSaved = true;
private bool JobSaved    
{ 
    get => jobSaved; 
    set
    {
        if (value == jobSaved) return;
        jobSaved = value;

        OnPropertyChanged();
        OnPropertyChanged("EnableSaveButton");
    }
}

public bool EnableSaveButton => !jobSaved;

0
在 .NET Maui 中,使用 CommunityToolkit.MVVM,我们可以简单地按照以下步骤进行操作:
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsNotBusy))]
bool isBusy;

public bool IsNotBusy => !IsBusy;

这样,每当IsBusy被改变时,IsNotBusy也会被改变并得到通知。


0
在写了太多的 BooleanThisConverterBooleanThatConverter 之后,最终我写出了下面这个让我的生活变得轻松得多的转换器:
public class BooleanIffConverter: IValueConverter
{
    public object TrueValue { get; set; }
    public object FalseValue { get; set; }
    public bool NullValue { get; set; } = false;

    /// <inheritdoc />
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
        (bool) (value ?? this.NullValue) ? this.TrueValue : this.FalseValue;

    /// <inheritdoc />
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
        throw new NotSupportedException();
}
    }

现在我可以将它用于所有类型的布尔转换,如刷子、双精度、可见性等。具体来说,用于反转布尔值:

<converters:BooleanIffConverter
    x:Key="BoolInverter"
    TrueValue="False"
    FalseValue="True" />

默认情况下,它将null视为false。如果需要相反的结果,请将NullValue设置为"True"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接