簡體   English   中英

C# WPF IsEnabled 使用多個綁定?

[英]C# WPF IsEnabled using multiple bindings?

我有一個描述 GUI 部分的 WPF xaml 文件,我希望特定控件的啟用/禁用依賴於其他兩個控件。 代碼現在看起來像這樣:

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

但我希望它也依賴於另一個復選框,例如:

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

go 的最佳方法是什么? 我不禁覺得我遺漏了一些明顯的東西或以錯誤的方式解決這個問題?

您可以將MultiBinding與實現IMultiValueConverter的轉換器IMultiValueConverter

只需給出答案,您就可以(幾乎)復制並粘貼:

需要的靜態資源:

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

ComboBox:

<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.");
        }
    }
}

您也可以嘗試相同的較短版本:

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

我相信您可能必須使用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

作為qqbenq答案的擴展:

添加了處理Collection的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;
    }
}

命名空間 <theNamespace:IsEnabledConverter x:Key="IsEnabledConverter"/>

按鍵

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

當您不想使用 MultiBinding 時

public class AndEnabledTextBox : TextBox
{
    public static readonly DependencyProperty AndEnabled1SubProperty =
        DependencyProperty.Register(nameof(AndEnabled1), typeof(bool), typeof(AndEnabledTextBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnAndEnabledPropertyChanged)));
    public static readonly DependencyProperty AndEnabled2SubProperty =
        DependencyProperty.Register(nameof(AndEnabled2), typeof(bool), typeof(AndEnabledTextBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnAndEnabledPropertyChanged)));
    public bool AndEnabled1 { get { return (bool)GetValue(AndEnabled1SubProperty); } set { SetValue(AndEnabled1SubProperty, value); } }
    public bool AndEnabled2 { get { return (bool)GetValue(AndEnabled2SubProperty); } set { SetValue(AndEnabled2SubProperty, value); } }
    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);
        IsEnabled = AndEnabled1 && AndEnabled2;
    }
    protected static void OnAndEnabledPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        AndEnabledTextBox textBox = (AndEnabledTextBox)obj;
        textBox.IsEnabled = textBox.AndEnabled1 && textBox.AndEnabled2;
    }
}

當您使用繼承的控件時, XMAL更加簡化。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApp1">
    <StackPanel>
        <ToggleButton x:Name="switch1" Content="{Binding ElementName=switch1, Path=IsChecked}"/>
        <ToggleButton x:Name="switch2" Content="{Binding ElementName=switch2, Path=IsChecked}"/>
        <local:AndEnabledTextBox Text="TEXT"
                                 AndEnabled1="{Binding ElementName=switch1, Path=IsChecked, Mode=OneWay}"
                                 AndEnabled2="{Binding ElementName=switch2, Path=IsChecked, Mode=OneWay}"/>
    </StackPanel>
</Window>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM