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

Rus*_*uss 356 wpf styles .net-3.5

我拥有的是具有IsReadOnly属性的对象.如果此属性为true,我想将IsEnabledButton(例如)上的属性设置为false.

我想相信我可以轻松地做到这一点,IsEnabled="{Binding Path=!IsReadOnly}"但不能与WPF一起使用.

我不得不经历所有的风格设置吗?对于像将一个bool设置为另一个bool的反向那样简单的事情,似乎太过冗长.

<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>
Run Code Online (Sandbox Code Playgroud)

Chr*_*col 462

您可以使用ValueConverter为您反转bool属性.

XAML:

IsEnabled="{Binding Path=IsReadOnly, Converter={StaticResource InverseBooleanConverter}}"
Run Code Online (Sandbox Code Playgroud)

转换器:

[ValueConversion(typeof(bool), typeof(bool))]
    public class InverseBooleanConverter: IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            if (targetType != typeof(bool))
                throw new InvalidOperationException("The target must be a boolean");

            return !(bool)value;
        }

        public object ConvertBack(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }

        #endregion
    }
Run Code Online (Sandbox Code Playgroud)

  • 我使用相同的方法...但它使熊猫saaad ... =( (50认同)
  • 与`!`相比,这是一些冗长的代码......人们花费了大量精力将他们认为"代码"的东西与那些可怜的设计师分开.当我既是编码员又是设计师时,额外的痛苦. (26认同)
  • 根据您自己的观点,恕我直言,转换器解决方案从长远来看更好:您只需要编写一次转换器,之后您可以反复使用它.如果你去新房产,你将不得不在每个需要它的类中重写它... (16认同)
  • 包括我在内的很多人会认为这是过度工程的一个主要例子.我建议使用倒置属性,如下面的Paul Alexander帖子. (10认同)
  • 我必须在这里考虑一些事情,这可能会让我选择@Paul的答案.编码时(现在),我自己就是这样,所以我需要一个"我"会记住的解决方案,我会一遍又一遍地使用它.我也觉得不那么罗嗦的东西越好,创造一个反向属性是非常明确的,让我很容易记住,以及未来的开发者(我希望,我希望),能够快速看到我正在做,并且让他们更容易把我扔到众所周知的公共汽车下面. (8认同)
  • **Xceed.Wpf.DataGrid**包含一些转换器.这个InverseBooleanConverter包含在该程序集中.我有一个ResourceDictionary`xmlns:xcdg ="http://schemas.xceed.com/wpf/xaml/datagrid"`这个资源`<xcdg:InverseBooleanConverter x:Key ="InverseBooleanConverter"/>` (4认同)
  • 在我看来,每次我需要以不同的方式绑定一些东西时,转换器比向我的类添加属性更优雅.如果没有转换器,我的许多类都将充斥着在我的代码中无用的属性.此外,如果我想为Visibility使用布尔属性,我还需要在我的类中引用WPF可见性枚举.如果您想保持代码清洁,我相信转换器是可行的方法.(1) (4认同)
  • 我认为它只是在 Microsoft 应该提供此转换器而不是期望每个人通过制作自己的转换器来重新发明轮子的方面过度设计。 (3认同)
  • 所以我使用的是MultiBinding,它的转换器简单地将几个内部布尔绑定合并在一起.其中一个内部布尔绑定恰好使用此InverseBooleanConverter.由于目标类型现在是System.Object(即MultiBinding元素)而不是System.Boolean(即布尔属性),因此转换器无法执行目标类型bool检查异常. (2认同)

Pau*_*der 97

你考虑过IsNotReadOnly房产吗?如果绑定的对象是MVVM域中的ViewModel,则附加属性非常有意义.如果它是直接实体模型,您可以考虑组合并向表单呈现实体的专用ViewModel.

  • 我不同意这种方法比价值转换器更好.如果您需要多个NotProperty实例,它还会生成更多代码. (28认同)
  • MVVM不是不编写代码,而是以声明方式解决问题.为此,转换器*是正确的解决方案. (25认同)
  • 此解决方案的问题是,如果您有100个对象,则必须向所有100个对象添加IsNotReadOnly属性.该属性必须是DependencyProperty.这为所有100个对象或1000行代码增加了大约10行代码.转换器是20行代码.1000行或20行.你会选哪个? (13认同)
  • 对此有一个常见的说法:做一次,做两次,然后自动化.有疑问的是,我会在项目中第一次使用这个答案,然后如果事情发展,我会使用接受的答案.但是,预制转换器片段可能会降低使用难度. (8认同)
  • 我刚刚使用这种方法解决了同样的问题,我同意它不仅比使用转换器更优雅,而且更易于维护. (5认同)
  • IMO,这是首选的解决方案.MVVM是要走的路.虽然转换器可以完成这项工作,但如果您可以首先避免使用代码......请给我+1. (3认同)
  • 通常,我倾向于使用相同的方法,但是在这种情况下,我不喜欢每次必须通知IsReadOnly属性的更改时也要记住也要通知IsNotReadOnly属性的事实,否则我将无法对齐接口。从逻辑上讲,它们是相同的属性,我不希望对其有两种不同的表示形式,最终无法对齐。 (2认同)

Ale*_*141 66

使用标准装订,您需要使用看起来有风的转换器.因此,我建议您查看我的项目CalcBinding,它是专门为解决此问题而开发的.使用高级绑定,您可以直接在xaml中编写具有许多源属性的表达式.说,你可以这样写:

<Button IsEnabled="{c:Binding Path=!IsReadOnly}" />
Run Code Online (Sandbox Code Playgroud)

要么

<Button Content="{c:Binding ElementName=grid, Path=ActualWidth+Height}"/>
Run Code Online (Sandbox Code Playgroud)

要么

<Label Content="{c:Binding A+B+C }" />
Run Code Online (Sandbox Code Playgroud)

要么

<Button Visibility="{c:Binding IsChecked, FalseToVisibility=Hidden}" />
Run Code Online (Sandbox Code Playgroud)

其中A,B,C,IsChecked - viewModel的属性,它将正常工作

祝好运!

  • 虽然QuickConverter功能更强大,但我发现CalcBinding模式可读 - 可用. (6认同)
  • 这是一个很棒的工具.我希望它存在于5年前! (3认同)

Nox*_*xys 20

我建议使用https://quickconverter.codeplex.com/

然后,反转布尔值就像这样简单: <Button IsEnabled="{qc:Binding '!$P', P={Binding IsReadOnly}}" />

这加快了编写转换器通常所需的时间.

  • 当给某人一个-1时,解释原因会很好. (16认同)

小智 13

我希望我的XAML保持尽可能优雅,所以我创建了一个类来包装驻留在我的一个共享库中的bool,隐式运算符允许该类在代码隐藏中无缝地用作bool

public class InvertableBool
{
    private bool value = false;

    public bool Value { get { return value; } }
    public bool Invert { get { return !value; } }

    public InvertableBool(bool b)
    {
        value = b;
    }

    public static implicit operator InvertableBool(bool b)
    {
        return new InvertableBool(b);
    }

    public static implicit operator bool(InvertableBool b)
    {
        return b.value;
    }

}
Run Code Online (Sandbox Code Playgroud)

项目所需的唯一更改是使您想要反转的属性返回而不是bool

    public InvertableBool IsActive 
    { 
        get 
        { 
            return true; 
        } 
    }
Run Code Online (Sandbox Code Playgroud)

并且在XAML后缀中绑定了Value或Invert

IsEnabled="{Binding IsActive.Value}"

IsEnabled="{Binding IsActive.Invert}"
Run Code Online (Sandbox Code Playgroud)

  • 缺点是,即使不引用反值,您也必须更改将其与其他“bool”类型表达式/变量进行比较/将其分配给其他“bool”类型表达式/变量的所有代码。相反,我会向 `Boolean` `Struct` 添加一个“Not”扩展方法。 (2认同)

Ωme*_*Man 11

.Net核心解决方案

处理 null 情况,不抛出异常,但true如果没有值则返回;否则获取输入的布尔值并将其反转。

public class BooleanToReverseConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
     => !(bool?) value ?? true;

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
     => !(value as bool?);
}
Run Code Online (Sandbox Code Playgroud)

沙姆尔

IsEnabled="{Binding IsSuccess Converter={StaticResource BooleanToReverseConverter}}"
Run Code Online (Sandbox Code Playgroud)

App.Xaml我喜欢将所有转换器静态数据放在 app.xaml 文件中,这样我就不必在项目的整个窗口/页面/控件中重新声明它们。

<Application.Resources>
    <converters:BooleanToReverseConverter x:Key="BooleanToReverseConverter"/>
    <local:FauxVM x:Key="VM" />
</Application.Resources>
Run Code Online (Sandbox Code Playgroud)

需要明确的 converters:是实际类实现的命名空间 ( xmlns:converters="clr-namespace:ProvingGround.Converters")。


And*_*eas 9

这个也适用于可空的布尔.

 [ValueConversion(typeof(bool?), typeof(bool))]
public class InverseBooleanConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (targetType != typeof(bool?))
        {
            throw new InvalidOperationException("The target must be a nullable boolean");
        }
        bool? b = (bool?)value;
        return b.HasValue && !b.Value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return !(value as bool?);
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)


小智 6

在您的视图模型中再添加一个属性,它将返回反向值。并将其绑定到按钮。喜欢;

在视图模型中:

public bool IsNotReadOnly{get{return !IsReadOnly;}}
Run Code Online (Sandbox Code Playgroud)

在 xaml 中:

IsEnabled="{Binding IsNotReadOnly"}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。要添加的一件事,使用它您最好在属性 IsReadOnly 的 setter 中为 IsNotReadOnly 增加 PropertyChanged 事件。有了这个,您将确保 UI 正确更新。 (2认同)