datatrigger on enum, aby zmienić obraz


101

Mam przycisk ze stałym obrazem tła i chciałbym pokazać na nim mały obraz nakładki. Wybór obrazu nakładki zależy od właściwości zależności ( LapCounterPingStatus) odpowiedniego modelu widoku.

Oto, co osiągnąłem do tej pory:

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

Odpowiednie części mojego modelu widoku

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

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

W tej chwili w ogóle nie jest wyświetlany obraz nakładki. Co się stało?


AKTUALIZACJA

Wyświetla się okno śledzenia mojego IDE System.ArgumentExceptioni System.FormatException. Czy źródłem problemu może być nieznany typ wyliczenia PingStatusw języku XAML?


Powiązane: stackoverflow.com/q/10250925/590790 Chociaż ten facet już to działa.
Steven Jeuris

Odpowiedzi:


249

Aby to działało, potrzebujesz 2 rzeczy:

1 - Dodaj xmlnsodwołanie w elemencie głównym pliku XAML, do przestrzeni nazw, w której zdefiniowano Enum:

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

2 - na Valuewłasność DataTriggernależy skorzystać z {x:Static}formularza:

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

Zwróć uwagę, że typ Enum musi być poprzedzony prefiksem xmlns zdefiniowanym powyżej.

Edytować:

Jeśli Twój Enum jest zadeklarowany wewnątrz klasy, musisz użyć składni:

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

na przykład:

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


1
Dodałem xmlnstak: xmlns:local="clr-namespace:MyCompany.Testbench"i taki spust <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">. Nie, pojawia się błąd Cannot find the type 'PingStatus'.
nabulke

1
enum PingStatusjest zdefiniowana w klasie MyCompany.TestBench.ConfigurationViewModel. Czy muszę gdzieś dodać nazwę klasy?
nabulke

3
Dziękuję Ci. Nigdzie nie mogłem znaleźć składni dla typu zagnieżdżonego. Gdzie jest udokumentowana składnia „+”? Nie mogę go znaleźć w MSDN ani w książkach WPF, które posiadam. Pomyślałem, że powinno być w rozszerzeniu x: Static Markup, ale tak nie jest.
skst

1
@skst Symbol + odróżnia typ zawierający od zagnieżdżonej przestrzeni nazw. Type t = typeof (System.Environment.SpecialFolder); Console.WriteLine (t.FullName); // prints System.Environment+SpecialFolder


3

Kompletny działający przykład dla WPF + MVVM.

Testowane na MSVC 2017.

W widoku:

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

W przypadku korzystania z ReSharper, a jeżeli DataContext jest ustawiony prawidłowo, nie będzie intellisense gdy trafisz .po StatusIcon, czyli pokaże właściwości wyliczenia, które są Debug, Info, Warninglub Error.

Jeśli używasz ReSharper, zasugeruje następującą aktualizację przestrzeni nazw w nagłówku pliku XAML (tak dobrze):

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

Oraz VieModel:

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

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

Używamy również Fodydo automatycznego wiązania.


Czy masz na myśli projekt PropertyChanged firmy Fody?
UuDdLrLrSs
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.