datatrigger в перечислении для изменения изображения

101

У меня есть кнопка с фиксированным фоновым изображением, и я хотел бы показать небольшое оверлейное изображение поверх нее. Выбор изображения наложения зависит от свойства зависимости ( LapCounterPingStatus) соответствующей модели просмотра.

Вот что у меня получилось:

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

Соответствующие части моей модели просмотра

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

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

Прямо сейчас наложенное изображение не отображается. Что могло быть не так?


ОБНОВИТЬ

В окне трассировки моей IDE отображается System.ArgumentExceptionи System.FormatException. Может ли источник проблемы быть неизвестным типом перечисления PingStatusв XAML?

набулька
источник
Связанный: stackoverflow.com/q/10250925/590790 Хотя у этого парня он уже работает.
Стивен Джеурис

Ответы:

249

Чтобы это работало, вам нужны 2 вещи:

1 - Добавьте xmlnsссылку в корневой элемент вашего XAML-файла в пространство имен, в котором определено ваше Enum:

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

2 - в Valueсвойстве DataTriggerиспользуйте {x:Static}форму:

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

Обратите внимание, что тип Enum должен иметь префикс xmlns, который вы определили выше.

Редактировать:

Если ваш Enum объявлен внутри класса, вам нужно использовать синтаксис:

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

например:

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

Федерико Берасатеги
источник
1
Я добавил вот xmlnsтак: xmlns:local="clr-namespace:MyCompany.Testbench"и триггер вот так <DataTrigger Binding="{Binding Path=LapCounterPingStatus}" Value="{x:Static local:PingStatus.PING_UNKNOWN}">. Нет, я получаю сообщение об ошибке Cannot find the type 'PingStatus'.
набульке
1
enum PingStatusопределяется внутри класса MyCompany.TestBench.ConfigurationViewModel. Надо ли мне где-нибудь добавить имя класса?
набульке
3
Спасибо. Я нигде не мог найти синтаксис для вложенного типа. Где задокументирован синтаксис "+"? Я не могу найти его в MSDN или в имеющихся у меня книгах по WPF. Я думал, что это должно быть в x: Static Markup Extension, но это не так.
skst
1
@skst Символ + отличает содержащий тип от вложенного пространства имен. Type t = typeof (System.Environment.SpecialFolder); Console.WriteLine (t.FullName); // prints System.Environment+SpecialFolder
3

Полный рабочий пример для WPF + MVVM.

Проверено на MSVC 2017.

В представлении:

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

Если вы используете ReSharper и если DataContext настроен правильно, то при нажатии на « .after» будет отображаться intellisense StatusIcon, т.е. он покажет свойства перечисления Debug, например Info, Warningили Error.

При использовании ReSharper он предложит следующее обновление пространства имен в заголовке файла XAML (это хорошо):

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

И VieModel:

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

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

Мы также используем Fodyдля автоматической привязки.

Контанго
источник
Вы имеете в виду проект PropertyChanged Фоди?
UuDdLrLrSs