datatrigger en enumeración para cambiar la imagen

100

Tengo un botón con una imagen de fondo fija y me gustaría mostrar una pequeña imagen superpuesta encima. Qué imagen de superposición elegir depende de una propiedad de dependencia ( LapCounterPingStatus) del modelo de vista correspondiente.

Esto es lo que tengo hasta ahora:

<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 de mi modelo de vista

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

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

En este momento, no se muestra ninguna imagen superpuesta. ¿Qué podría estar mal?


ACTUALIZAR

Se muestra la ventana de seguimiento de mi IDE System.ArgumentExceptiony System.FormatException. ¿Podría la fuente del problema ser un tipo desconocido de enumeración PingStatusen el XAML?

nabulke
fuente
Relacionado: stackoverflow.com/q/10250925/590790 Aunque este tipo ya lo hizo funcionar.
Steven Jeuris

Respuestas:

247

Necesita 2 cosas para que esto funcione:

1 - Agregue una xmlnsreferencia en el elemento raíz de su archivo XAML, al espacio de nombres donde se define su Enum:

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

2 - en Valuepropiedad del DataTrigger, use el {x:Static}formulario:

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

Tenga en cuenta que el tipo Enum debe tener el prefijo xmlns que definió anteriormente.

Editar:

Si su Enum se declara dentro de una clase, debe usar la sintaxis:

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

por ejemplo:

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

Federico Berasategui
fuente
1
Agregué algo xmlnsasí: xmlns:local="clr-namespace:MyCompany.Testbench"y el disparador así <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">. No, me sale el error Cannot find the type 'PingStatus'.
Nabulke
1
enum PingStatusse define dentro de la clase MyCompany.TestBench.ConfigurationViewModel. ¿Tengo que agregar el nombre de la clase en alguna parte?
Nabulke
3
Gracias. No pude encontrar la sintaxis de un tipo anidado en ninguna parte. ¿Dónde está documentada la sintaxis "+"? No puedo encontrarlo en MSDN o en los libros de WPF que tengo. Pensé que debería estar en x: Static Markup Extension, pero no lo es.
skst
1
@skst El símbolo + diferencia el tipo contenedor de un espacio de nombres anidado. Type t = typeof (System.Environment.SpecialFolder); Console.WriteLine (t.FullName); // prints System.Environment+SpecialFolder
2

Ejemplo completo trabajado para WPF + MVVM.

Probado en MSVC 2017.

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

Si se utiliza ReSharper, y si el DataContext está configurado correctamente, habrá IntelliSense cuando se pulse el .después StatusIcon, es decir, que mostrará las propiedades de la enumeración que son Debug, Info, Warningo Error.

Si usa ReSharper, sugerirá la siguiente actualización del espacio de nombres en el encabezado del archivo XAML (es bueno así):

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

Y el VieModel:

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

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

También utilizamos Fodypara la vinculación automática.

Aplazamiento de pago
fuente
¿Te refieres al proyecto PropertyChanged de Fody?
UuDdLrLrSs