WPF Event Handlers and Property Triggers


Imagine that you want the color of a control on your GUI to turn blue when the mouse pointer hovers over it. In your WPF program, you can do this with property triggers. You can also accomplish this with event handlers. In the example program for this post, we do both.

The example program called PropertyTrigger has one property trigger on the first Open Text File button. When the mouse is over the Open Text File button the text (content) turns red. When the mouse is removed from the top of the button the text returns to the black color. You don’t need to write event handlers. You can do this in XAML and save time and effort.

When you click on the Open File button a Windows dialog box appears and asks you to select a text file. This is a common dialog. You can click the Wrap button to wrap the text of the file inside the TextBox. There is also a No Wrap button that when clicked removes any wrapping from the text in the TextBox. The Wrap and NoWrap buttons use click events and have code behind that changes the property of the TextBox. When the code behind changes the value of the TextWrapping property changes take effect immediately. The colored boxes are not buttons. They are rectangles. Why? When you hover over a button its color changes to blue and I didn’t want that behaviour. I need to button to stay the same color. Because I couldn’t figure out how do change this behavior, I used rectangles and the MouseLeftButtonUp event to change the background of the TextBox. To let the user know that the mouse pointer had entered the space of the rectangle, I used an asynchronous event MouseEnterAsync to change the rectangle’s Fill color to White, delay for 40 milliseconds and change the color back.

<Window x:Class="PropertyTrigger.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:PropertyTrigger"
        mc:Ignorable="d"
        WindowStartupLocation="CenterScreen"
        Title="PropertyTrigger" Height="600" Width="700" MinHeight="180" MinWidth="170">
    <DockPanel Margin="6">
        <WrapPanel DockPanel.Dock="Top" >
            <Button Name="btnOpenFile" Click="btnOpenFile_Click" Width="Auto" Height="23" Margin="3,10,10,10" Padding="3">
               <Button.Style>
                   <Style TargetType="{x:Type Button}">
                       <Style.Triggers>
                          <Trigger Property="IsMouseOver" Value="True">
                             <Setter Property="Foreground" Value="Red"/>
                          </Trigger>
                       </Style.Triggers>
                   </Style>
               </Button.Style>
               Open Text File for Viewing
            </Button>
            <!-- Button and rectangle margins are set in App.xaml -->
            <Button Name="btnWrap" Click="btnWrap_Click" Height="23" Padding="3" ToolTip="Wrap">Wrap</Button>
            <Button Name="btnUnWrap" Click="btnUnWrap_Click" Height="23" Padding="3" ToolTip="Unwrap">Unwrap</Button>
            <Rectangle Name="rctAqua" Height="23" Width="23" Fill="Aqua" 
                        MouseLeftButtonUp="rctAqua_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctAqua_MouseEnterAsync" ToolTip="Aqua"/>
            <Rectangle Name="rctBeige" Height="23" Width="23" Fill="Beige" 
                        MouseLeftButtonUp="rctBeige_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctBeige_MouseEnterAsync" ToolTip="Beige"/>
            <Rectangle Name="rctAzure" Height="23" Width="23" Fill="Azure" 
                        MouseLeftButtonUp="rctAzure_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctAzure_MouseEnterAsync" ToolTip="Azure"/>
            <Rectangle Name="rctFloralWhite" Height="23" Width="23" Fill="FloralWhite" 
                        MouseLeftButtonUp="rctFloralWhite_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctFloralWhite_MouseEnterAsync" ToolTip="FloralWhite"/>
            <Rectangle Name="rctGhostWhite" Height="23" Width="23" Fill="GhostWhite" 
                        MouseLeftButtonUp="rctGhostWhite_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctGhostWhite_MouseEnterAsync" ToolTip="GhostWhite"/>
            <Rectangle Name="rctWhiteSmoke" Height="23" Width="23" Fill="WhiteSmoke" 
                        MouseLeftButtonUp="rctWhiteSmoke_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctWhiteSmoke_MouseEnterAsync" ToolTip="WhiteSmoke"/>
            <Rectangle Name="rctHoneydew" Height="23" Width="23" Fill="Honeydew" 
                        MouseLeftButtonUp="rctHoneydew_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctHoneydew_MouseEnterAsync" ToolTip="Honeydew"/>
            <Rectangle Name="rctIvory" Height="23" Width="23" Fill="Ivory" 
                        MouseLeftButtonUp="rctIvory_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctIvory_MouseEnterAsync" ToolTip="Ivory"/>
            <Rectangle Name="rctLavender" Height="23" Width="23" Fill="Lavender" 
                        MouseLeftButtonUp="rctLavender_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctLavender_MouseEnterAsync" ToolTip="Lavender"/>
            <Rectangle Name="rctLemonChiffon" Height="23" Width="23" Fill="LemonChiffon" 
                        MouseLeftButtonUp="rctLemonChiffon_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctLemonChiffon_MouseEnterAsync" ToolTip="LemonChiffon"/>
            <Rectangle Name="rctLightGray" Height="23" Width="23" Fill="LightGray" 
                        MouseLeftButtonUp="rctLightGray_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctLightGray_MouseEnterAsync" ToolTip="LightGray"/>
            <Rectangle Name="rctLightYellow" Height="23" Width="23" Fill="LightYellow" 
                        MouseLeftButtonUp="rctLightYellow_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctLightYellow_MouseEnterAsync" ToolTip="LightYellow"/>
            <Rectangle Name="rctMintCream" Height="23" Width="23" Fill="MintCream" 
                        MouseLeftButtonUp="rctMintCream_MouseLeftButtonUp" Stroke="DarkGray" StrokeThickness="1"
                       MouseEnter="rctMintCream_MouseEnterAsync" ToolTip="MintCream"/>
        </WrapPanel>
        <Label Name="lblFile" DockPanel.Dock="Bottom" Content=" "></Label>
        <TextBox Name="txtViewer" ScrollViewer.HorizontalScrollBarVisibility="Auto"
                Margin="3"
                Background="White"
                ScrollViewer.VerticalScrollBarVisibility="Auto"
                ScrollViewer.CanContentScroll="True" TextWrapping="NoWrap" />
    </DockPanel>
</Window>

Below is the C# code behind.

using System;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.IO;
using Microsoft.Win32;
namespace PropertyTrigger
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        int intDelay = 40;

        public MainWindow()
        {
            InitializeComponent();
        }
        private void btnOpenFile_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            if (openFileDialog.ShowDialog() == true)
                txtViewer.Text = File.ReadAllText(openFileDialog.FileName);
            lblFile.Content = openFileDialog.FileName;

        }
        private void btnWrap_Click(object sender, RoutedEventArgs e)
        {
            txtViewer.TextWrapping = TextWrapping.Wrap;
            // once this is set, it automatically takes effect.
        }
        //
        private void btnUnWrap_Click(object sender, RoutedEventArgs e)
        {
            txtViewer.TextWrapping = TextWrapping.NoWrap;
            // once this is set, it automatically takes effect.
        }
        private void rctAqua_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.Aqua;
        }
        private async void rctAqua_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.Aqua;
            }  
        }
        private void rctBeige_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.Beige;
        }
        private async void rctBeige_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.Beige;
            }
        }
        private void rctAzure_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.Azure;
        }
        private async void rctAzure_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.Azure;
            }
        }
        //FloralWhite
        private void rctFloralWhite_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.FloralWhite;
        }
        private async void rctFloralWhite_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.FloralWhite;
            }
        }
        // GhostWhite
        private void rctGhostWhite_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.GhostWhite;
        }
        private async void rctGhostWhite_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.GhostWhite;
            }
        }
        // WhiteSmoke
        private void rctWhiteSmoke_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.WhiteSmoke;
        }
        private async void rctWhiteSmoke_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.WhiteSmoke;
            }
        }
        // Honeydew
        private void rctHoneydew_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.Honeydew;
        }
        private async void rctHoneydew_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.Honeydew;
            }
        }
        // Ivory
        private void rctIvory_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.Ivory;
        }
        private async void rctIvory_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.Ivory;
            }
        }
        // Lavender
        private void rctLavender_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.Lavender;
        }
        private async void rctLavender_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.Lavender;
            }
        }
        // LemonChiffon
        private void rctLemonChiffon_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.Ivory;
        }
        private async void rctLemonChiffon_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.LemonChiffon;
            }
        }
        // LightGray
        private void rctLightGray_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.LightGray;
        }
        private async void rctLightGray_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.LightGray;
            }
        }
        // LightYellow
        private void rctLightYellow_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.LightYellow;
        }
        private async void rctLightYellow_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.LightYellow;
            }
        }
        // MintCream
        private void rctMintCream_MouseLeftButtonUp(object sender, RoutedEventArgs e)
        {
            txtViewer.Background = Brushes.MintCream;
        }
        private async void rctMintCream_MouseEnterAsync(object sender, RoutedEventArgs e)
        {
            Rectangle r = sender as Rectangle;
            if (r != null)
            {
                r.Fill = Brushes.White;
                await Task.Delay(intDelay);
                r.Fill = Brushes.MintCream;
            }
        }
    }
}

In the screenshot below you can see that the user has clicked on the honeydew color and left the mousepointer there so that the tooltip is visible.