Siva
Siva

Reputation: 1411

How to load different images on different events of a button control using MVVM?

Using MVVM architecture, I want to load an image on a button. As I have similar button in many places I want to make this as common.

1) Initially when the form is launched an image should be loaded.

2) When "MouseEnter" event then cursor image should change to hand.

3) When "MouseLeave" event then cursor image should change to Arrow.

4) When "MouseLeftButtonDown" then an image should be loaded.

5) When "MouseLeftButtonUp" then an image should be loaded.

Like this, I want to load different images on different events and this button needs to be used in many other dialogs. How can design it such that it can be as a common resource for all.

Could any one please help me to solve this issue.

I am very new to WPF. Please be kind with your answers.

Upvotes: 0

Views: 65

Answers (1)

J.H.
J.H.

Reputation: 4322

You could use attached properties for this. If you need different events, then you will have to add more attached properties.

Note that #2 and #3 could simply be Cursor="Hand" on the button. There is nothing to implement for #3 - the cursor will change on it's own when you leave the button. I added it as an attached property just for fun. It is completely useless and really just duplicates Cursor="Hand".

disk_blue.png, disk_green.png and disk_yellow.png were added to the root of the application by just dragging and dropping them onto the project in Visual Studio. The build action is "Resource".

Here is a complete demo app:

XAML:

<Window x:Class="WpfApplication56.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:WpfApplication56"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:VM InitialImage="disk_blue.png" MouseLeftButtonDownImage="disk_green.png" MouseLeftButtonUpImage="disk_yellow.png" />
    </Window.DataContext>
    <Grid>
        <Button VerticalAlignment="Center" HorizontalAlignment="Center" Padding="20"
                local:MyButton.MouseEnterCursor="Hand"
                local:MyButton.InitialImage="{Binding InitialImage}"
                local:MyButton.MouseLeftButtonDown="{Binding MouseLeftButtonDownImage}"
                local:MyButton.MouseLeftButtonUp="{Binding MouseLeftButtonUpImage}"
        />
    </Grid>
</Window>

CS:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace WpfApplication56
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class VM // I didn't implement INotifyPropertyChanged because it doesn't matter for this question
    {
        public Uri InitialImage { get; set; }
        public Uri MouseLeftButtonDownImage { get; set; }
        public Uri MouseLeftButtonUpImage { get; set; }
    }

    public class MyButton
    {
        // Attached Properties
        #region MouseEnterCursorProperty
        public static Cursor GetMouseEnterCursor(DependencyObject obj)
        {
            return (Cursor)obj.GetValue(MouseEnterCursorProperty);
        }
        public static void SetMouseEnterCursor(DependencyObject obj, Cursor value)
        {
            obj.SetValue(MouseEnterCursorProperty, value);
        }
        public static readonly DependencyProperty MouseEnterCursorProperty = DependencyProperty.RegisterAttached("MouseEnterCursor", typeof(Cursor), typeof(MyButton), new PropertyMetadata(null, OnPropertyChanged));
        #endregion
        #region InitialImageProperty
        public static Uri GetInitialImage(DependencyObject obj)
        {
            return (Uri)obj.GetValue(InitialImageProperty);
        }
        public static void SetInitialImage(DependencyObject obj, Uri value)
        {
            obj.SetValue(InitialImageProperty, value);
        }
        public static readonly DependencyProperty InitialImageProperty = DependencyProperty.RegisterAttached("InitialImage", typeof(Uri), typeof(MyButton), new PropertyMetadata(null, OnPropertyChanged));
        #endregion
        #region MouseLeftButtonDownProperty
        public static Uri GetMouseLeftButtonDown(DependencyObject obj)
        {
            return (Uri)obj.GetValue(MouseLeftButtonDownProperty);
        }
        public static void SetMouseLeftButtonDown(DependencyObject obj, Uri value)
        {
            obj.SetValue(MouseLeftButtonDownProperty, value);
        }
        public static readonly DependencyProperty MouseLeftButtonDownProperty = DependencyProperty.RegisterAttached("MouseLeftButtonDown", typeof(Uri), typeof(MyButton), new PropertyMetadata(null, OnPropertyChanged));
        #endregion
        #region MouseLeftButtonUpProperty
        public static Uri GetMouseLeftButtonUp(DependencyObject obj)
        {
            return (Uri)obj.GetValue(MouseLeftButtonUpProperty);
        }
        public static void SetMouseLeftButtonUp(DependencyObject obj, Uri value)
        {
            obj.SetValue(MouseLeftButtonUpProperty, value);
        }
        public static readonly DependencyProperty MouseLeftButtonUpProperty = DependencyProperty.RegisterAttached("MouseLeftButtonUp", typeof(Uri), typeof(MyButton), new PropertyMetadata(null, OnPropertyChanged));
        #endregion

        // Called when the value for an attached property has changed
        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Button b = d as Button;
            if (b == null)
                return;

            if (e.Property.Equals(MouseEnterCursorProperty))
            {
                b.MouseEnter -= MouseEnter; // In case the property changes more than once we don't want to hook it more than once
                b.MouseEnter += MouseEnter;
            }
            else if (e.Property.Equals(InitialImageProperty))
            {
                SetButtonImage(b, GetInitialImage(b));
            }
            else if (e.Property.Equals(MouseLeftButtonDownProperty))
            {
                // Had to use Preview because non-Preview never fired
                b.PreviewMouseLeftButtonDown -= MouseLeftButtonDown;
                b.PreviewMouseLeftButtonDown += MouseLeftButtonDown;
            }
            else if (e.Property.Equals(MouseLeftButtonUpProperty))
            {
                // Had to use Preview because non-Preview never fired
                b.PreviewMouseLeftButtonUp -= MouseLeftButtonUp;
                b.PreviewMouseLeftButtonUp += MouseLeftButtonUp;
            }
        }

        private static void MouseEnter(object sender, MouseEventArgs e)
        {
            Button b = sender as Button;
            if (b == null)
                return;
            b.Cursor = GetMouseEnterCursor(b);
            e.Handled = false;
        }

        private static void MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Button b = sender as Button;
            if (b == null)
                return;
            SetButtonImage(b, GetMouseLeftButtonDown(b));
            e.Handled = false;
        }
        private static void MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Button b = sender as Button;
            if (b == null)
                return;
            SetButtonImage(b, GetMouseLeftButtonUp(b));
            e.Handled = false;
        }

        private static void SetButtonImage(Button b, Uri uri)
        {
            if (b == null || uri == null)
                return;

            var img = b.Content as Image;
            if (img == null)
                img = new Image();
            BitmapImage bm = new BitmapImage();
            bm.BeginInit();
            bm.UriSource = uri;
            bm.EndInit();
            img.Source = bm;

            b.Content = img;
        }
    }
}

Screenshots

Initial (mouse was over it to show cursor change but cursor isn't in the image):

enter image description here

LeftMouseButtonDown:

enter image description here

LeftMouseButtonUp:

enter image description here

Upvotes: 1

Related Questions