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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1039636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:37:21  来源:igfitidea点击:

How to bind inverse boolean properties in WPF?

wpf.net-3.5styles

提问by Russ

What I have is an object that has an IsReadOnlyproperty. If this property is true, I would like to set the IsEnabledproperty on a Button, ( for example ), to false.

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

I would like to believe that I can do it as easily as IsEnabled="{Binding Path=!IsReadOnly}"but that doesn't fly with WPF.

我想相信我可以像IsEnabled="{Binding Path=!IsReadOnly}"WPF一样轻松地做到这一点,但这并不适用。

Am I relegated to having to go through all of the style settings? Just seems too wordy for something as simple as setting one bool to the inverse of another 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>

回答by Chris Nicol

You can use a ValueConverter that inverts a bool property for you.

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

XAML:

XAML:

IsEnabled="{Binding Path=IsReadOnly, Converter={StaticResource InverseBooleanConverter}}"

Converter:

转换器:

[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
    }

回答by Paul Alexander

Have you considered an IsNotReadOnlyproperty? If the object being bound is a ViewModel in a MVVM domain, then the additional property makes perfect sense. If it's a direct Entity model, you might consider composition and presenting a specialized ViewModel of your entity to the form.

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

回答by Alex141

With standart binding you need to use converters that looks little windy. So, I recommend you to look at my project CalcBinding, which was developed specially to resolve this problem and some others. With advanced binding you can write expressions with many source properties directly in xaml. Say, you can write something like:

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

<Button IsEnabled="{c:Binding Path=!IsReadOnly}" />

or

或者

<Button Content="{c:Binding ElementName=grid, Path=ActualWidth+Height}"/>

or

或者

<Label Content="{c:Binding A+B+C }" />

or

或者

<Button Visibility="{c:Binding IsChecked, FalseToVisibility=Hidden}" />

where A, B, C, IsChecked - properties of viewModel and it will work properly

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

回答by Noxxys

I would recommend using https://quickconverter.codeplex.com/

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

Inverting a boolean is then as simple as: <Button IsEnabled="{qc:Binding '!$P', P={Binding IsReadOnly}}" />

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

That speeds the time normally needed to write converters.

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

回答by jevansio

I wanted my XAML to remain as elegant as possible so I created a class to wrap the bool which resides in one of my shared libraries, the implicit operators allow the class to be used as a bool in code-behind seamlessly

我希望我的 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;
    }

}

The only changes needed to your project are to make the property you want to invert return this instead of bool

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

    public InvertableBool IsActive 
    { 
        get 
        { 
            return true; 
        } 
    }

And in the XAML postfix the binding with either Value or Invert

在 XAML 后缀中,绑定值或反转

IsEnabled="{Binding IsActive.Value}"

IsEnabled="{Binding IsActive.Invert}"

回答by Andreas

This one also works for nullable bools.

这个也适用于可为空的布尔值。

 [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
}

回答by MMM

Add one more property in your view model, which will return reverse value. And bind that to button. Like;

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

in view model:

在视图模型中:

public bool IsNotReadOnly{get{return !IsReadOnly;}}

in xaml:

在 xaml 中:

IsEnabled="{Binding IsNotReadOnly"}

回答by EricG

I had an inversion problem, but a neat solution.

我有一个反转问题,但是一个巧妙的解决方案。

Motivation was that the XAML designer would show an empty control e.g. when there was no datacontext / no MyValues(itemssource).

动机是 XAML 设计器将显示一个空控件,例如,当没有数据MyValues上下文/否(项目源)时。

Initial code: hidecontrol when MyValuesis empty. Improved code: showcontrol when MyValuesis NOT null or empty.

初始代码:为空时隐藏控件MyValues。改进的代码:在非空或空时显示控制MyValues

Ofcourse the problem is how to express '1 or more items', which is the opposite of 0 items.

当然问题是如何表达'1个或多个项目',这与0个项目相反。

<ListBox ItemsSource={Binding MyValues}">
  <ListBox.Style x:Uid="F404D7B2-B7D3-11E7-A5A7-97680265A416">
    <Style TargetType="{x:Type ListBox}">
      <Style.Triggers>
        <DataTrigger Binding="{Binding MyValues.Count}">
          <Setter Property="Visibility" Value="Collapsed"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </ListBox.Style>
</ListBox>

I solved it by adding:

我通过添加解决了它:

<DataTrigger Binding="{Binding MyValues.Count, FallbackValue=0, TargetNullValue=0}">

Ergo setting the default for the binding. Ofcourse this doesn't work for all kinds of inverse problems, but helped me out with clean code.

Ergo 设置绑定的默认值。当然,这不适用于所有类型的逆问题,但帮助我解决了干净的代码。

回答by Simon Dobson

Don't know if this is relevant to XAML, but in my simple Windows app I created the binding manually and added a Format event handler.

不知道这是否与 XAML 相关,但在我的简单 Windows 应用程序中,我手动创建了绑定并添加了一个 Format 事件处理程序。

public FormMain() {
  InitializeComponent();

  Binding argBinding = new Binding("Enabled", uxCheckBoxArgsNull, "Checked", false, DataSourceUpdateMode.OnPropertyChanged);
  argBinding.Format += new ConvertEventHandler(Binding_Format_BooleanInverse);
  uxTextBoxArgs.DataBindings.Add(argBinding);
}

void Binding_Format_BooleanInverse(object sender, ConvertEventArgs e) {
  bool boolValue = (bool)e.Value;
  e.Value = !boolValue;
}

回答by ΩmegaMan

.Net Core Solution

.Net核心解决方案

Handles null situation and does not throw an exception, but returns trueif no value is presented; otherwise takes the inputted Boolean and reverses it.

处理空情况,不抛出异常,但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?);
}

Xaml

xml

IsEnabled="{Binding IsSuccess Converter={StaticResource BooleanToReverseConverter}}"


App.XamlI like to put all my converter statics in the app.xaml file so I don't have to redeclare them throughout the windows/pages/controls of the project.

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

<Application.Resources>
    <converters:BooleanToReverseConverter x:Key="BooleanToReverseConverter"/>
    <local:FauxVM x:Key="VM" />
</Application.Resources>

To be clear converters:is the namespace to the actual class implementation (xmlns:converters="clr-namespace:ProvingGround.Converters").

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