datatrigger on enum pour changer l'image


100

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

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

À l'heure actuelle, aucune image de superposition n'est affichée. Qu'est-ce qui ne va pas?


METTRE À JOUR

La fenêtre de trace de mon IDE s'affiche System.ArgumentExceptionet System.FormatException. La source du problème pourrait-elle être un type d'énumération inconnu dans PingStatusle XAML?


En relation: stackoverflow.com/q/10250925/590790 Bien que ce type l'ait déjà fait fonctionner.
Steven Jeuris

Réponses:


247

Vous avez besoin de 2 choses pour que cela fonctionne:

1 - Ajoutez une xmlnsréférence dans l'élément racine de votre fichier XAML, à l'espace de noms où votre Enum est défini:

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

2 - dans la Valuepropriété du 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écédé du préfixe xmlns que vous avez défini ci-dessus.

Éditer:

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

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

par exemple:

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


1
J'ai ajouté le xmlnscomme ceci: xmlns:local="clr-namespace:MyCompany.Testbench"et le déclencheur comme ça <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">. Non, j'obtiens l'erreur Cannot find the type 'PingStatus'.
nabulke

1
enum PingStatusest défini à l'intérieur de la classe MyCompany.TestBench.ConfigurationViewModel. Dois-je ajouter le nom de la classe quelque part?
nabulke

3
Je vous remercie. Je n'ai trouvé nulle part la syntaxe d'un type imbriqué. Où la syntaxe "+" est-elle documentée? Je ne peux pas le trouver dans MSDN ou dans les livres WPF que j'ai. Je pensais que cela devrait être dans x: Static Markup Extension mais ce n'est pas le cas.
skst

1
@skst Le symbole + différencie le type conteneur d'un espace de noms imbriqué. Type t = typeof (System.Environment.SpecialFolder); Console.WriteLine (t.FullName); // prints System.Environment+SpecialFolder


2

Exemple de travail complet 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 IntelliSense quand vous frappez la .suite StatusIcon, ce qu'il affiche les propriétés de l'ENUM qui sont Debug, Info, Warningou 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 (c'est bien 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 Fodypour la liaison automatique.


Faites-vous référence au projet PropertyChanged de Fody?
UuDdLrLrSs
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.