Путаница с Silverlight MVVM: обновление изображения в зависимости от состояния - PullRequest
1 голос
/ 17 февраля 2011

Я занимаюсь разработкой приложения Silverlight и пытаюсь придерживаться принципов MVVM, но сталкиваюсь с некоторыми проблемами при изменении источника изображения на основе состояния свойства в ViewModel. Для всех намерений и целей вы можете думать о функциональности, которую я реализую, как кнопку воспроизведения / паузы для аудио-приложения. В режиме «Воспроизведение» IsActive имеет значение true во ViewModel, и на кнопке должно отображаться изображение «Pause.png». Когда пауза, IsActive имеет значение false в ViewModel и «Play.png» отображается на кнопке. Естественно, есть два дополнительных изображения для обработки, когда мышь наводит курсор на кнопку.

Я думал, что смогу использовать Style Trigger , но, очевидно, они не поддерживаются в Silverlight. Я просматривал сообщение на форуме с вопросом, похожим на мой, где предлагается использовать VisualStateManager . Хотя это может помочь с изменением изображения для парящих / нормальных состояний, отсутствует часть (или я не понимаю), как это будет работать с состоянием, установленным через модель представления. Кажется, что пост относится только к событиям, а не к свойствам модели представления. Сказав это, я также не успешно выполнил обычные / парящие эффекты.

Ниже мой Silverlight 4 XAML. Также следует отметить, что я работаю с MVVM Light.

<UserControl x:Class="Foo.Bar.MyUserControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    mc:Ignorable="d"
    d:DesignHeight="100" d:DesignWidth="200">
    <UserControl.Resources>
        <Style x:Key="MyButtonStyle" TargetType="Button">
            <Setter Property="IsEnabled" Value="true"/>
            <Setter Property="IsTabStop" Value="true"/>
            <Setter Property="Background" Value="#FFA9A9A9"/>
            <Setter Property="Foreground" Value="#FF000000"/>
            <Setter Property="MinWidth" Value="5"/>
            <Setter Property="MinHeight" Value="5"/>
            <Setter Property="Margin" Value="0"/>
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Top" />
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Cursor" Value="Hand"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid>
                            <Image Source="/Foo.Bar;component/Resources/Icons/Bar/Play.png">
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="Active">
                                        <VisualState x:Name="MouseOver">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="/Foo.Bar;component/Resources/Icons/Bar/Play_Hover.png" />
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                            </Image>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <Button Style="{StaticResource MyButtonStyle}" Command="{Binding ChangeStatus}" Height="30" Width="30" />
    </Grid>
</UserControl>

Как правильно обновлять изображения на кнопках в состоянии, определяемом моделью вида?

Ответы [ 3 ]

1 голос
/ 18 февраля 2011

У нас есть несколько пользовательских преобразователей, которые изменяют логические (и другие типы) на конкретные изображения.Таким образом мы сохраняем представление / модель как можно более раздельными.

Конвертеры просты в написании, с множеством примеров в Интернете.

В xaml получается что-то вроде этого:

<Image Source={Binding IsActive, Converter={StaticResource "boolToPlayImageConverter"}}/>
1 голос
/ 21 февраля 2011

По совету коллеги, и так как я уже использовал MVVM Light , я смог использовать EventToCommand для обработки событий ввода и отпускания мыши в представлении модель, а не полагаться на встроенный VisualStateManager для обработки этих событий. Я также изменил мою кнопку на ToggleButton. Это позволило мне использовать отмеченные и непроверенные состояния для обработки отображения кнопок воспроизведения или паузы. Поскольку состояние контролировалось моделью представления, я смог определить, какое изображение отображать, связав атрибут Visibility элемента ToggleButton со свойством модели представления, которое проверяло состояние. Мой обновленный XAML выглядит следующим образом:

<UserControl x:Class="Foo.Bar.MyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4"
    mc:Ignorable="d"
    d:DesignHeight="100" d:DesignWidth="200">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <cmd:EventToCommand Command="{Binding MouseEnterCommand}" PassEventArgsToCommand="True"/>
        </i:EventTrigger>
        <i:EventTrigger EventName="MouseLeave">
            <cmd:EventToCommand Command="{Binding MouseLeaveCommand}" PassEventArgsToCommand="True"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <UserControl.Resources>
        <Style x:Key="MyButtonStyle" TargetType="ToggleButton">
            <Setter Property="IsEnabled" Value="true"/>
            <Setter Property="IsTabStop" Value="true"/>
            <Setter Property="Background" Value="#FFA9A9A9"/>
            <Setter Property="Foreground" Value="#FF000000"/>
            <Setter Property="MinWidth" Value="5"/>
            <Setter Property="MinHeight" Value="5"/>
            <Setter Property="Margin" Value="0"/>
            <Setter Property="HorizontalAlignment" Value="Left" />
            <Setter Property="HorizontalContentAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Top" />
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Cursor" Value="Hand"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToggleButton">
                        <Grid>
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CheckStates">
                                    <VisualState x:Name="Checked">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Pause">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Play">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Collapsed</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Unchecked">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Play">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Visible</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Pause">
                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                    <DiscreteObjectKeyFrame.Value>
                                                        <Visibility>Collapsed</Visibility>
                                                    </DiscreteObjectKeyFrame.Value>
                                                </DiscreteObjectKeyFrame>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Indeterminate" />
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Image x:Name="Play" Source="/Foo.Bar;component/Resources/Icons/Bar/Play.png" />
                            <Image x:Name="Pause" Source="/Foo.Bar;component/Resources/Icons/Bar/Pause.png" Visibility="Collapsed" />
                            <Image x:Name="PlayHover" Source="/Foo.Bar;component/Resources/Icons/Bar/Play_Hover.png" Visibility="{Binding PlayHoverVisible,FallbackValue=Collapsed}" />
                            <Image x:Name="PauseHover" Source="/Foo.Bar;component/Resources/Icons/Bar/Pause_Hover.png" Visibility="{Binding PauseHoverVisible,FallbackValue=Collapsed}" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <ToggleButton Style="{StaticResource MyButtonStyle}" IsChecked="{Binding IsPlaying}" Command="{Binding ChangeStatus}" Height="30" Width="30" />
    </Grid>
</UserControl>
1 голос
/ 18 февраля 2011

Простой способ - это связать логическое свойство IsActive и IsNotActive на вашей виртуальной машине с видимостью на двух элементах управления Image внутри содержимого вашей кнопки.

Вы, конечно, должны использовать BooleanToVisiblityConverter.

Вторая мысль: Не могли бы вы привязать IsActive к IsEnabled на своей кнопке и заставить стиль показать правильное изображение. Не уверен, что ограничение, упомянутое вами в Silverlight, может помешать этому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...