WPF使用多个变量绑定到布尔表达式的可见性

11

我有两个布尔值,我想根据它们的值显示图像,类似于这样:

   <Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>

<Image Visibility="{Binding (Boolean1 && Boolean2),Converter={StaticResource BooleanToVisibilityConverter}}" />

注意 Boolean1 和 Boolean2 表达式。


1
绑定路径不支持这种表达式,请在视图模型中创建一个只读属性 public bool Boolean3 { get { return Boolean1 && Boolean2; }},然后将其绑定到 Boolean3。 - ASh
有没有更简单的方法来内联执行这样的操作? - Stacker
你需要使用Multibinding和Multivalueconverter。http://www.codearsenal.net/2013/12/wpf-multibinding-example.html#.WKrPW_LNjMM - MikeT
根据我的回答,要么使用IMultiValueConverter,要么使用具有MultiDataTrigger的Style。 - mm8
@Slacker,实际上允许您直接在视图中编写代码将会破坏整个MVVM概念,外观和功能必须分离。 - MikeT
4个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
21

XAML 中没有定义 && 运算符,但您可以绑定到多个属性并使用 IMultiValueConverter

<Image>
    <Image.Visibility>
        <MultiBinding Converter="{StaticResource YourMultiConverter}">
            <Binding Path="Boolean1" />
            <Binding Path="Boolean2" />
        </MultiBinding>
    </Image.Visibility>
</Image>

public class YourMultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool a = (bool)values[0];
        bool b = (bool)values[1];

        return a && b ? Visibility.Visible : Visibility.Collapsed;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

或者你可以使用带有条件的 Image 样式:

<Image>
    <Image.Style>
        <Style TargetType="Image">
            <Setter Property="Visibility" Value="Collapsed" />
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Boolean1}" Value="True" />
                        <Condition Binding="{Binding Boolean2}" Value="True" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Visibility" Value="Visible" />
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </Image.Style>
</Image>

抱歉,这是一个愚蠢的问题,如何定义 ({StaticResource YourMultiConverter})? - Stacker
@Stacker,定义任何转换器的方式都一样,只需将其创建为相关资源字典中的静态资源,只要记得如果您还没有定义命名空间,您需要定义它。 - MikeT
1
<Window.Resources> 中的 <local:YourMultiValueConverter x:Key="YourMultiValueConverter "/>。 - mm8
在 ConvertBack 中应返回 null,因为: “数据绑定引擎无法捕获由用户提供的转换器抛出的异常。ConvertBack 方法抛出的任何异常或 ConvertBack 方法调用的方法抛出的任何未捕获异常都将被视为运行时错误。通过返回 null 处理预期的问题。” - Rudy Barbieri

5

mm8已经给出了正确的答案,不过稍微改进一下应该会更好。

public class LogicalAndConverter : IMultiValueConverter
{
    public IValueConverter FinalConverter{get;set;}

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool rtn = values.All(v=>(bool)v);

        if(FinalConverter==null)    
            return rtn;
        else
            return FinalConverter.Convert(rtn,targetType,parameter,culture);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

这样做可以让您在不重写多功能转换器的情况下使用不同的转换器。

<local:LogicalAndConverter x:Key="LogicalAndConverter ">
    <local:LogicalAndConverter.FinalConverter>
        <BooleanToVisibilityConverter />
    </local:LogicalAndConverter.FinalConverter>
</local:LogicalAndConverter>

这是一个被低估的答案。非常流畅的转换器管道。 - Cheesi
我喜欢这个答案,因为它很灵活! - hfann

2
如果您不介意在项目中添加另一个包,DevExpress的MVVM框架(可免费使用)具有称为DXBinding的绑定标记扩展,允许编写绑定函数/表达式。
<Image Visibility="{DXBinding 'Boolean1 and Boolean2', Converter={StaticResource BooleanToVisibilityConverter}}"/>

0
你可以使用多值转换器来解决这个问题 XAML:
 <TextBlock Name="textBlockOutput" Grid.Row="4" Grid.Column="2">
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource MultiValueConverter}">
                <Binding Path="TextOne" />
                <Binding Path="TextTwo" />
                <Binding Path="TextThree" />
            </MultiBinding>
        </TextBlock.Text>
    </TextBlock>




 public class MultiValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        string one = values[0] as string;
        string two = values[1] as string;
        string three = values[2] as string;
        if(!string.IsNullOrEmpty(one) && !string.IsNullOrEmpty(two) && !string.IsNullOrEmpty(three))
        {
            return one + two + three;
        }
        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

虽然您的答案是正确的,但更好的解释为什么这样修复会改进它作为答案。 - MikeT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,