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

我愿意相信我可以像IsEnabled="{绑定路径=!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>

当前回答

这个方法也适用于可为空的bool。

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

其他回答

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

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

I did something very similar. I created my property behind the scenes that enabled the selection of a combobox ONLY if it had finished searching for data. When my window first appears, it launches an async loaded command but I do not want the user to click on the combobox while it is still loading data (would be empty, then would be populated). So by default the property is false so I return the inverse in the getter. Then when I'm searching I set the property to true and back to false when complete.

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" />

这个方法也适用于可为空的bool。

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

我遇到了一个倒置的问题,但是有一个简洁的解决方法。

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

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

当然,问题是如何表达“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>

我通过添加:

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

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

我建议使用https://github.com/JohannesMoersch/QuickConverter

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

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