Datatrigger auf Aufzählung, um das Bild zu ändern

100

Ich habe eine Schaltfläche mit einem festen Hintergrundbild und möchte ein kleines Überlagerungsbild darüber anzeigen. Welches Overlay-Bild ausgewählt werden soll, hängt von einer Abhängigkeitseigenschaft ( LapCounterPingStatus) des entsprechenden Ansichtsmodells ab.

Das habe ich bisher bekommen:

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

Relevante Teile meines Ansichtsmodells

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

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

Derzeit wird überhaupt kein Überlagerungsbild angezeigt. Was könnte falsch sein?


AKTUALISIEREN

Das Trace-Fenster meiner IDE wird angezeigt System.ArgumentExceptionund System.FormatException. Könnte die Problemquelle eine unbekannte Art der Aufzählung in PingStatusder XAML sein?

Nabulke
quelle
Siehe auch : stackoverflow.com/q/10250925/590790 Obwohl dieser Typ es bereits zum Laufen gebracht hat .
Steven Jeuris

Antworten:

247

Sie benötigen zwei Dinge, um dies zum Laufen zu bringen:

1 - Fügen xmlnsSie im Namespace, in dem Ihre Enum definiert ist, eine Referenz im Stammelement Ihrer XAML-Datei hinzu:

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

2 - Verwenden Sie in der ValueEigenschaft von DataTriggerdas folgende {x:Static}Formular:

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

Beachten Sie, dass dem Aufzählungstyp das oben definierte XML-Präfix vorangestellt werden muss.

Bearbeiten:

Wenn Ihre Aufzählung in einer Klasse deklariert ist, müssen Sie die folgende Syntax verwenden:

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

beispielsweise:

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

Federico Berasategui
quelle
1
Ich habe das xmlnsFolgende hinzugefügt : xmlns:local="clr-namespace:MyCompany.Testbench"und den Auslöser so <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">. Nein, ich bekomme den Fehler Cannot find the type 'PingStatus'.
Nabulke
1
enum PingStatuswird innerhalb der Klasse definiert MyCompany.TestBench.ConfigurationViewModel. Muss ich den Klassennamen irgendwo hinzufügen?
Nabulke
3
Danke dir. Ich konnte die Syntax für einen verschachtelten Typ nirgendwo finden. Wo ist die "+" - Syntax dokumentiert? Ich kann es nicht in MSDN oder in den WPF-Büchern finden, die ich habe. Ich dachte, es sollte in x: Static Markup Extension sein, aber es ist nicht.
Skst
1
@skst Das Symbol + unterscheidet den enthaltenen Typ von einem verschachtelten Namespace. Type t = typeof (System.Environment.SpecialFolder); Console.WriteLine (t.FullName); // prints System.Environment+SpecialFolder
2

Vollständiges Beispiel für WPF + MVVM.

Getestet am MSVC 2017.

In der Ansicht:

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

Bei der Verwendung von ReSharper, und wenn die Datacontext richtig eingerichtet ist, wird es Intellisense, wenn Sie den Hit .nach StatusIcon, dh er die Eigenschaften des ENUM zeigen , die sind Debug, Info, Warningoder Error.

Wenn Sie ReSharper verwenden, wird die folgende Aktualisierung des Namespace im Header für die XAML-Datei vorgeschlagen (es ist gut so):

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

Und das VieModel:

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

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

Wir verwenden auch Fodyfür die automatisierte Bindung.

Contango
quelle
Beziehen Sie sich auf das PropertyChanged-Projekt von Fody?
UuDdLrLrSs