datatrigger no enum para mudar a imagem

100

Eu tenho um botão com uma imagem de plano de fundo fixa e gostaria de mostrar uma pequena imagem de sobreposição em cima dele. A imagem de sobreposição a ser escolhida depende de uma propriedade de dependência ( LapCounterPingStatus) do modelo de visualização de acordo.

Isso é o que eu tenho até agora:

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

Partes relevantes do meu modelo de visão

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

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

No momento, nenhuma imagem de sobreposição é exibida. O que pode estar errado?


ATUALIZAR

A janela de rastreamento do meu IDE está sendo exibida System.ArgumentExceptione System.FormatException. A origem do problema pode ser um tipo desconhecido de enumeração PingStatusno XAML?

Nabulke
fonte
Relacionado: stackoverflow.com/q/10250925/590790 Embora esse cara já tenha feito isso funcionar.
Steven Jeuris

Respostas:

247

Você precisa de 2 coisas para fazer isso funcionar:

1 - Adicione uma xmlnsreferência no elemento raiz de seu arquivo XAML, ao namespace onde seu Enum está definido:

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

2 - na Valuepropriedade da DataTrigger, utilize o {x:Static}formulário:

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

Observe que o tipo Enum deve ser prefixado com o prefixo xmlns definido acima.

Editar:

Se o seu Enum for declarado dentro de uma classe, você precisará usar a sintaxe:

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

por exemplo:

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

Federico Berasategui
fonte
1
Eu adicionei xmlnsassim: xmlns:local="clr-namespace:MyCompany.Testbench"e o gatilho assim <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">. Não, recebo o erro Cannot find the type 'PingStatus'.
nabulke
1
enum PingStatusé definido dentro da classe MyCompany.TestBench.ConfigurationViewModel. Eu tenho que adicionar o nome da classe em algum lugar?
nabulke
3
Obrigado. Não consegui encontrar a sintaxe de um tipo aninhado em qualquer lugar. Onde a sintaxe "+" está documentada? Não consigo encontrar no MSDN ou nos livros do WPF que tenho. Achei que deveria estar em x: Static Markup Extension, mas não é.
skst
1
@skst O símbolo + diferencia o tipo de conteúdo de um namespace aninhado. Type t = typeof (System.Environment.SpecialFolder); Console.WriteLine (t.FullName); // prints System.Environment+SpecialFolder
2

Exemplo completo trabalhado para WPF + MVVM.

Testado em MSVC 2017.

Na 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 estiver usando ReSharper, e se o DataContext está configurado corretamente, haverá intellisense quando você bate o .depois StatusIcon, ou seja, ele vai mostrar as propriedades da enumeração que são Debug, Info, Warningou Error.

Se estiver usando ReSharper, ele irá sugerir a seguinte atualização para o namespace no cabeçalho do arquivo XAML (é bom assim):

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

E o VieModel:

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

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

Também usamos Fodypara vinculação automática.

Contango
fonte
Você está se referindo ao projeto PropertyChanged de Fody?
UuDdLrLrSs