115 votes

datatrigger sur l'enum pour changer d'image

J'ai un bouton avec une image d'arrière-plan fixe et je voudrais afficher une petite image en superposition par-dessus. L'image de recouvrement à choisir dépend d'une propriété de dépendance ( LapCounterPingStatus ) du modèle de vue correspondant.

C'est ce que j'ai obtenu jusqu'à présent :

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

Parties pertinentes de mon modèle de vue

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

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

Pour l'instant, aucune image superposée ne s'affiche. Quel est le problème ?


UPDATE

La fenêtre de traçage de mon IDE montre System.ArgumentException y System.FormatException . La source du problème pourrait-elle être un type d'énumération inconnu ? PingStatus im le XAML ?

275voto

HighCore Points 23088

Vous avez besoin de 2 choses pour que ça marche :

1 - Ajouter un xmlns dans l'élément Root de votre fichier XAML, vers l'espace de nom où votre Enum est définie :

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

2 - dans la Value de l DataTrigger utilisez le {x:Static} formulaire :

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

Notez que le type Enum doit être préfixé avec le préfixe xmlns que vous avez défini ci-dessus.

Edit :

Si votre Enum est déclarée dans une classe, vous devez utiliser la syntaxe suivante :

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

par exemple :

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

4voto

Contango Points 7976

Exemple complet de travail pour WPF + MVVM.

Testé sur MSVC 2017.

Dans la vue :

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

Si vous utilisez ReSharper, et si le DataContext est correctement configuré, il y aura un intellisense lorsque vous frapperez la touche . après StatusIcon c'est-à-dire qu'il montrera les propriétés de l'enum qui sont Debug , Info , Warning ou Error .

Si vous utilisez ReSharper, il suggérera la mise à jour suivante de l'espace de noms dans l'en-tête du fichier XAML (son bon comme ça) :

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

Et le VieModel :

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

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

Nous utilisons également Fody pour la reliure automatisée.

2voto

Adam Silenko Points 2397

Vous pouvez simplement définir la valeur de l'enum comme valeur du DataTrigger... Testé sur 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>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X