datatrigger su enum per cambiare immagine


100

Ho un pulsante con un'immagine di sfondo fissa e vorrei mostrare una piccola immagine sovrapposta sopra di essa. Quale immagine sovrapposta scegliere dipende da una proprietà di dipendenza ( LapCounterPingStatus) del rispettivo viewmodel.

Questo è quello che ho ottenuto finora:

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

Parti rilevanti del mio viewmodel

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

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

Al momento, non viene visualizzata alcuna immagine sovrapposta. Cosa potrebbe esserci di sbagliato?


AGGIORNARE

La finestra di traccia del mio IDE sta mostrando System.ArgumentExceptione System.FormatException. La fonte del problema potrebbe essere un tipo sconosciuto di enumerazione PingStatusnel XAML?


Correlato: stackoverflow.com/q/10250925/590790 Anche se questo ragazzo lo ha già funzionato.
Steven Jeuris

Risposte:


247

Hai bisogno di 2 cose per farlo funzionare:

1 - Aggiungi un xmlnsriferimento nell'elemento radice del tuo file XAML, allo spazio dei nomi in cui è definito il tuo Enum:

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

2 - nella Valueproprietà della DataTrigger, utilizzare il {x:Static}modulo:

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

Si noti che il tipo Enum deve essere preceduto dal prefisso xmlns definito sopra.

Modificare:

Se il tuo Enum è dichiarato all'interno di una classe devi usare la sintassi:

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

per esempio:

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


1
Ho aggiunto xmlnscosì: xmlns:local="clr-namespace:MyCompany.Testbench"e il grilletto così <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">. No ricevo l'errore Cannot find the type 'PingStatus'.
nabulke

1
enum PingStatusè definito all'interno della classe MyCompany.TestBench.ConfigurationViewModel. Devo aggiungere il nome della classe da qualche parte?
nabulke

3
Grazie. Non sono riuscito a trovare la sintassi per un tipo annidato da nessuna parte. Dove è documentata la sintassi "+"? Non riesco a trovarlo in MSDN o nei libri WPF che ho. Ho pensato che dovrebbe essere in x: Static Markup Extension ma non lo è.
skst

1
@skst Il simbolo + differenzia il tipo contenitore da uno spazio dei nomi nidificato. Type t = typeof (System.Environment.SpecialFolder); Console.WriteLine (t.FullName); // prints System.Environment+SpecialFolder


2

Esempio di lavoro completo per WPF + MVVM.

Testato su MSVC 2017.

Nella vista:

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

Se si utilizza ReSharper, e se il DataContext è impostato correttamente, ci saranno IntelliSense quando si preme il .dopo StatusIcon, vale a dire che mostrerà le proprietà della enum che sono Debug, Info, Warningo Error.

Se si utilizza ReSharper, suggerirà il seguente aggiornamento allo spazio dei nomi nell'intestazione del file XAML (va bene così):

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

E il VieModel:

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

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

Usiamo anche Fodyper l'associazione automatica.


Ti riferisci al progetto PropertyChanged di Fody?
UuDdLrLrSs
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.