多值单数据触发WPF

时间:2019-04-08 14:41:09

标签: c# .net wpf windows

我有以下一段代码。

                <Button.Style>
                    <Style BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
                           TargetType="{x:Type Button}">
                        <Setter Property="Visibility" Value="Collapsed" />
                        <Style.Triggers>

                            <DataTrigger Binding="{Binding Status, Mode=OneWay}"
                                         Value="{x:Static comm:DeviceStatus.Standby}">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>

                            <DataTrigger Binding="{Binding Status, Mode=OneWay}"
                                         Value="{x:Static comm:DeviceStatus.Busy}">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>

                            <DataTrigger Binding="{Binding Status, Mode=OneWay}"
                                         Value="{x:Static comm:DeviceStatus.Offline}">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>

                            <DataTrigger Binding="{Binding Status, Mode=OneWay}"
                                         Value="{x:Static comm:DeviceStatus.StartingStream}">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>

                            <DataTrigger Binding="{Binding Status, Mode=OneWay}"
                                         Value="{x:Static comm:DeviceStatus.Connecting}">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>

                            <DataTrigger Binding="{Binding Status, Mode=OneWay}"
                                         Value="{x:Static comm:DeviceStatus.Disconnecting}">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>

                            <DataTrigger Binding="{Binding Status, Mode=OneWay}"
                                         Value="{x:Static comm:DeviceStatus.DownloadingFiles}">
                                <Setter Property="Visibility" Value="Visible" />
                            </DataTrigger>

                        </Style.Triggers>
                    </Style>
                </Button.Style>

默认情况下,该按钮是隐藏的,并且当视图模型中的一个属性中只有几个值时可见。该属性是一个名为DeviceStatus的枚举类型。

基本上,它对提供的触发器执行“或”运算。 因此,按钮的可见性取决于:状态== StandBy ||状态==忙|| ...

如何在没有8个触发器的情况下实现此功能?

我想要以下内容:

<DataTrigger Binding="{Binding Status, Mode=OneWay}">
    <DataTrigger.AnyValue>
        <AnyValueItem Value="{x:Static comm:DeviceStatus.Standby}" />
        <AnyValueItem Value="{x:Static comm:DeviceStatus.Busy}" />
        <AnyValueItem Value="{x:Static comm:DeviceStatus.Offline}" />
        ...
    </DataTrigger.AnyValue>
    <Setter Property="Visibility" Value="Visible" />
</DataTrigger>

如果绑定获得任何提供的值,则将“按钮的可见性”设置为“可见”。 谢谢!

3 个答案:

答案 0 :(得分:1)

DataTrigger不支持某种可能的值列表。它只有一个Value属性。

解决此问题的最简单方法是向视图模型添加一个属性,该属性返回一个指示是否显示Button的值:

public bool IsVisible => Status == Standby || Status == Busy || ...;

XAML:

<DataTrigger Binding="{Binding IsVisible, Mode=OneWay}" Value="True">
    <Setter Property="Visibility" Value="Visible" />
</DataTrigger>

另一种选择是使用@ 33t建议的converter。然后,您只需将逻辑移出视图模型,例如:

public class Converter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        ViewModel vm = value as ViewModel;
        return (vm != null && (vm.Status == Standby || vm.Status == Busy || ...)) ? Vsibility.Visible : Visibility.Collapsed;
    }

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

XAML:

<Style ...>
    <Style.Resources>
        <local:Converter x:Key="conv" />
    </Style>
    <Setter Property="Visibility" Value="{Binding Path=., Converter={StaticResource converter}}" />

答案 1 :(得分:1)

您可以做一个财产:

private DeviceStatus _Status;
    public DeviceStatus Status
    {
        get { return _Status; }
        set
        {
            this.Set(ref _Status, value);
            RaisePropertyChanged(nameof(this.StatusVisibility));
        }
    }

    public Visibility StatusVisibility
    {
        get
        {
            switch (_Status)
            {
                case DeviceStatus.Busy: //add other statuses here
                    return Visibility.Visible;
            }

            return Visibility.Collapsed;
        }
    }

,然后在您的按钮中:

<Button Content="MyButton" Visibility="{Binding StatusVisibility}"></Button>

答案 2 :(得分:0)

阅读答案后,我有了一些想法,找到了令人满意的可扩展解决方案。

首先,我创建了以下转换器。

public sealed class EnumOrConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

        DeviceStatus status = (DeviceStatus)value;

        DeviceStatus[] statuses = parameter as DeviceStatus[];

        if (statuses.Any(s => s == status))
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

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

第二,我只是将以下代码添加到XAML中。

<Button Command="{Binding SomeCommand}">
    <Button.Style>
        <Style BasedOn="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
                           TargetType="{x:Type Button}">
            <Setter Property="Visibility">
                <Setter.Value>
                    <Binding Path="Status" Converter="{StaticResource EnumOrConverter}">
                        <Binding.ConverterParameter>
                            <x:Array Type="{x:Type comm:DeviceStatus}">
                                <x:Static Member="comm:DeviceStatus.Standby" />
                                <x:Static Member="comm:DeviceStatus.Busy" />
                                <x:Static Member="comm:DeviceStatus.Offline" />
                                <x:Static Member="comm:DeviceStatus.StartingStream" />
                                <x:Static Member="comm:DeviceStatus.Connecting" />
                                <x:Static Member="comm:DeviceStatus.Disconnecting" />
                                <x:Static Member="comm:DeviceStatus.DownloadingFiles" />
                            </x:Array>
                        </Binding.ConverterParameter>
                    </Binding>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>

这使我可以将转换器逻辑重用于许多其他按钮,而无需向ViewModel添加变量或属性。同样发生的是,转换器封装了“或:给”参数和“默认为Visibility.Collapsed”的逻辑。而且,添加新参数只需要XAML中的一行代码即可。