【问题标题】:C# WPF IsEnabled using multiple bindings?C# WPF IsEnabled 使用多个绑定?
【发布时间】:2010-10-31 00:48:06
【问题描述】:

我有一个 WPF xaml 文件,描述了 GUI 的一部分,我希望特定控件的启用/禁用依赖于其他两个控件。代码现在看起来像这样:

<ComboBox Name="MyComboBox"
          IsEnabled="{Binding ElementName=SomeCheckBox, Path=IsChecked}"/>

但我希望它也依赖于另一个复选框,例如:

<ComboBox Name="MyComboBox"
          IsEnabled="{Binding ElementName=SomeCheckBox&AnotherCheckbox, Path=IsChecked}"/>

最好的方法是什么?我不禁觉得我遗漏了一些明显的东西或以错误的方式解决这个问题?

【问题讨论】:

    标签: c# wpf binding combobox isenabled


    【解决方案1】:

    您可以将MultiBinding 与实现IMultiValueConverter 的转换器一起使用。

    只是为了给出答案,您可以(几乎)复制和粘贴:

    需要静态资源:

    <converterNamespace:BooleanAndConverter x:Key="booleanAndConverter" />
    

    组合框:

    <ComboBox Name="MyComboBox">
      <ComboBox.IsEnabled>
        <MultiBinding Converter="{StaticResource booleanAndConverter}">
          <Binding ElementName="SomeCheckBox" Path="IsChecked" />
          <Binding ElementName="AnotherCheckbox" Path="IsChecked"  />
        </MultiBinding>
      </ComboBox.IsEnabled>
    </ComboBox>
    

    转换器的代码:

    namespace ConverterNamespace
    {
        public class BooleanAndConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                foreach (object value in values)
                {
                    if ((value is bool) && (bool)value == false)
                    {
                        return false;
                    }
                }
                return true;
            }
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotSupportedException("BooleanAndConverter is a OneWay converter.");
            }
        }
    }
    

    【讨论】:

    • 我有一个问题,如果 values 为 null 怎么办?一开始有这样的支票不是更好吗:if (values == null) { return false; }
    • ConvertBack 方法应该返回 null 而不是抛出 NotSupportedExceptionaccording to MSDN
    • 在我看来,使用 LinQ 转换方法更容易理解:return values.All(value =&gt; value is bool &amp;&amp; (bool) value);return values.All(value =&gt; value is bool b &amp;&amp; b);
    • 我知道这是旧的,但我使用了这种 LinQ 语法:return values.OfType&lt;bool&gt;().All(x =&gt; x);
    • 如果我需要不同的转换器怎么办?
    【解决方案2】:

    您也可以尝试较短的版本:

    public class BooleanAndConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return values.OfType<IConvertible>().All(System.Convert.ToBoolean);
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    
    public class BooleanOrConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return values.OfType<IConvertible>().Any(System.Convert.ToBoolean);
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    

    当然,您可能还需要转换器来提高可见性:

    public class BooleanOrToVisibilityConverter : IMultiValueConverter
    {
        public Visibility HiddenVisibility { get; set; }
    
        public bool IsInverted { get; set; }
    
        public BooleanOrToVisibilityConverter()
        {
            HiddenVisibility = Visibility.Collapsed;
            IsInverted = false;
        }
    
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            bool flag = values.OfType<IConvertible>().Any(System.Convert.ToBoolean);
            if (IsInverted) flag = !flag;
            return flag ? Visibility.Visible : HiddenVisibility;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    
    public class BooleanAndToVisibilityConverter : IMultiValueConverter
    {
        public Visibility HiddenVisibility { get; set; }
    
        public bool IsInverted { get; set; }
    
        public BooleanAndToVisibilityConverter()
        {
            HiddenVisibility = Visibility.Collapsed;
            IsInverted = false;
        }
    
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            bool flag = values.OfType<IConvertible>().All(System.Convert.ToBoolean);
            if (IsInverted) flag = !flag;
            return flag ? Visibility.Visible : HiddenVisibility;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    【讨论】:

    • 有没有办法把这些链接起来?
    【解决方案3】:

    我相信您可能必须将 MultiBinding 与 MultiValueConverter 一起使用。见这里:http://www.developingfor.net/wpf/multibinding-in-wpf.html

    这是一个直接相关的例子:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/5b9cd042-cacb-4aaa-9e17-2d615c44ee22

    【讨论】:

      【解决方案4】:

      作为qqbenq回答的延伸:

      添加了处理集合的Count 的功能,例如,如果您想检查是否选择了ListView 的某些项目。

      转换器:

      public class IsEnabledConverter : IMultiValueConverter
      {
          public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
          {
              foreach (var value in values)
              {
                  switch (value)
                  {
                      case bool b when !b:
                      case int i when i == 0:
                          return false;
                  }
              }
      
              return true;
          }
      
          public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
          {
              return null;
          }
      }
      

      命名空间 &lt;theNamespace:IsEnabledConverter x:Key="IsEnabledConverter"/&gt;

      按钮

      <Button x:Name="MyButton">
          <Button.IsEnabled>
              <MultiBinding Converter="{StaticResource IsEnabledConverter}">
                  <Binding ElementName="MyListView" Path="SelectedItems.Count"/>
                  <Binding ElementName="MyCheckBox" Path="IsChecked"/>
              </MultiBinding>
          </Button.IsEnabled>
      </Button>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-04
        • 1970-01-01
        • 2018-01-21
        • 1970-01-01
        • 2012-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多