profou
profou

Reputation: 217

Image not change by using visual states

Why do my visual states not work when the dependency property Message is NULL or filled ?

WPF code:

<Window x:Class="VisualStateTest.MainWindow"
        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:local="clr-namespace:VisualStateTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Border x:Name="border" Background="Black">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="LocationErrorStatusVisualStateGroup">
                <VisualState x:Name="DefaultVisualState">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Image.Source)" Storyboard.TargetName="myImage">
                            <DiscreteObjectKeyFrame KeyTime="0">
                                <DiscreteObjectKeyFrame.Value>
                                    <BitmapImage UriSource="/VisualStateTest;component/Resources/Empty.png"/>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="MessageVisualState">
                    <Storyboard>
                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Image.Source)" Storyboard.TargetName="myImage">
                            <DiscreteObjectKeyFrame KeyTime="0">
                                <DiscreteObjectKeyFrame.Value>
                                    <BitmapImage UriSource="/VisualStateTest;component/Resources/Message.png"/>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Image x:Name="myImage"/>
    </Border>
</Window>

C# code behind:

using System.Windows;

namespace VisualStateTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        #region Message

        /// <summary>
        /// Message Dependency Property
        /// </summary>
        public static readonly DependencyProperty MessageProperty =
            DependencyProperty.Register("Message", typeof(string), typeof(MainWindow),
                new FrameworkPropertyMetadata(null,
                    new PropertyChangedCallback(OnMessageChanged)));

        /// <summary>
        /// Gets or sets the Message property. This dependency property 
        /// indicates the message.
        /// </summary>
        public string Message
        {
            get { return (string)GetValue(MessageProperty); }
            set { SetValue(MessageProperty, value); }
        }

        /// <summary>
        /// Handles changes to the Message property.
        /// </summary>
        private static void OnMessageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MainWindow target = (MainWindow)d;
            string oldMessage = (string)e.OldValue;
            string newMessage = target.Message;
            target.OnMessageChanged(oldMessage, newMessage);
        }

        /// <summary>
        /// Provides derived classes an opportunity to handle changes to the Message property.
        /// </summary>
        protected virtual void OnMessageChanged(string oldMessage, string newMessage)
        {
            if (newMessage == oldMessage)
                return;

            if (string.IsNullOrEmpty(newMessage))
            {
                VisualStateManager.GoToState(this, "DefaultVisualState", true);
            }
            else
            {
                VisualStateManager.GoToState(this, "MessageVisualState", true);
            }
        }

        #endregion

        public MainWindow()
        {
            Message = "test";
            InitializeComponent();
        }
    }
}

Upvotes: 1

Views: 187

Answers (1)

Ehssan
Ehssan

Reputation: 759

The build action of the images should be set to Resource. The images should then be referenced using Pack URIs which would be

pack://application:,,,/Resources/Empty.png
pack://application:,,,/Resources/Message.png

There are two ways to use the VisualStateManager. The visual states can be defined:

  • either in the template of a control, or
  • directly in the control (as you are doing here)

When the visual states are not defined within a template, you have to call the GoToElementState method rather than the GoToState method.

Also, you have to call the GoToElementState method on the control that actually defines the corresponding visual states, so you need to call it on the Border and not on the MainWindow

VisualStateManager.GoToElementState(border, "DefaultVisualState", true);

See here for more details on the VisualStateManager

Upvotes: 0

Related Questions