枚举类型的DataTrigger用于改变图像

120

我有一个带固定背景图像的按钮,并希望在其顶部显示一个小的覆盖图像。选择哪个覆盖图像取决于相应视图模型的依赖属性(LapCounterPingStatus)。

到目前为止,我得到了这个:

<Button>
    <Grid>
        <Image Stretch="None"> <!-- Background Image -->
            <Image.Style>
                <Style TargetType="{x:Type Image}">
                    <Setter Property="Source" Value="/Images/Pingn.png"/>
                </Style>
            </Image.Style>
        </Image>
        <Image Stretch="None" Panel.ZIndex="1"> <!-- Small Overlay Image -->
            <Image.Style>
                <Style TargetType="{x:Type Image}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="PingStatus.PING_UNKNOWN">
                            <Setter Property="Source" Value="/Images/RefreshOverlayn.png"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="PingStatus.PING_FAILURE">
                            <Setter Property="Source" Value="/Images/ErrorOverlayn.png"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="PingStatus.PING_SUCCESS">
                            <Setter Property="Source" Value="/Images/CheckmarkOverlayn.png"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Image.Style>
        </Image>
    </Grid>
</Button>

我的视图模型的相关部分

public class ConfigurationViewModel
{
    public enum PingStatus { PING_UNKNOWN, PING_SUCCESS, PING_FAILURE };

    public PingStatus LapCounterPingStatus
    {
        get { return _lapCounterPingStatus; }
        set
        {
            _lapCounterPingStatus = value;
            RaisePropertyChanged(LapCounterPingStatusPropertyName);
        }
    }
}

现在,完全没有叠加图像显示。可能出了什么问题?


更新

我的 IDE 的跟踪窗口显示 System.ArgumentExceptionSystem.FormatException。问题源是否可能是 XAML 中未知枚举类型 PingStatus


相关链接:https://dev59.com/3GLVa4cB1Zd3GeqP1PBS 尽管这个人已经让它工作了。 - Steven Jeuris
3个回答

293

使此功能正常工作,需要以下两个步骤:

1-在XAML文件的根元素中添加xmlns引用,指向定义Enum的命名空间:

<UserControl ...
xmlns:my="clr-namespace:YourEnumNamespace;assembly=YourAssembly"> 

2 - 在 DataTriggerValue 属性中使用 {x:Static} 形式:

 <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static my:PingStatus.PING_UNKNOWN}">

注意,枚举类型必须以你在上面定义的 xmlns 前缀作为前缀。

编辑:

如果您的枚举声明在一个类内部,则需要使用以下语法:

{x:Static namespace:ClassName+EnumName.EnumValue}

例如:

{x:Static my:ConfigurationViewModel+PingStatus.PING_UNKNOWN}


1
我像这样添加了 xmlnsxmlns:local="clr-namespace:MyCompany.Testbench",并且触发器是这样的 <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">。现在我收到了错误信息 Cannot find the type 'PingStatus' - nabulke
1
enum PingStatus 定义在 MyCompany.TestBench.ConfigurationViewModel 类内部。我需要在某个地方添加类名吗? - nabulke
3
谢谢。我无法找到嵌套类型的语法。"+" 语法在哪里有文档记录?我在 MSDN 或我手头的 WPF 书籍中都找不到它。我以为应该在 x:Static Markup Extension 中,但没找到。 - skst
1
加号符号将包含类型与嵌套命名空间区分开来。 Type t = typeof(System.Environment.SpecialFolder); Console.WriteLine(t.FullName); // 输出 System.Environment+SpecialFolder - user5157912
2
@skst https://dev59.com/8HE95IYBdhLWcg3wHqWl@skst https://dev59.com/8HE95IYBdhLWcg3wHqWl%E7%B1%BB%E5%90%8D%E4%B8%AD%E5%8C%85%E5%90%AB-a - user5157912
显示剩余4条评论

6

完整的WPF + MVVM工作示例。

在MSVC 2017上测试通过。

在视图中:

<TextBlock Text="Some text to be colored by an enum">
    <TextBlock.Style>
        <Style TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding StatusIcon}" Value="{x:Static my:StatusIcon.Warning}">
                    <Setter Property="Foreground" Value="Yellow"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding StatusIcon}" Value="{x:Static my:StatusIcon.Error}">
                    <Setter Property="Foreground" Value="Red}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

如果使用 ReSharper,并且 DataContext 被正确设置,当你在 StatusIcon 后按下 . 时,将会有智能提示,即它将显示枚举的属性,这些属性为 DebugInfoWarningError

如果使用 ReSharper,它会建议更新 XAML 文件头中的命名空间(这样很好):

xmlns:my="clr-namespace:Class.Path.MyViewModel;assembly=MyAssembly"

还有ViewModel:

public enum StatusIcon
{
    Debug,
    Info,
    Warning,
    Error
}

public class MyViewModel
{
    public StatusIcon StatusIcon { get; }
}

我们还使用Fody进行自动绑定。


你是在指Fody的PropertyChanged项目吗? - StayOnTarget

4
您可以将枚举值设置为DataTrigger的值... 在MSVC 2017上测试通过。
<TextBlock Text="Some text to be colored by an enum">
    <TextBlock.Style>
        <Style TargetType="{x:Type TextBlock}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding StatusIcon}" Value="Warning">
                    <Setter Property="Foreground" Value="Yellow"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding StatusIcon}" Value="Error">
                    <Setter Property="Foreground" Value="Red}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

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