Friday, February 11, 2011

A simple WPF fading popup control

Steps:

1.) Create a WPF Project in Visual Studio.  I named mine FadingPopup. (Note: You can use 3.5 or 4.0, but you will need to use 4.0 if you want to take advantage of the animation EasingFunctions.)
2.) Add a User Control with the following code:

FadingPopupControl.xaml

<UserControl x:Class="FadingPopup.FadingPopupControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" BorderThickness="0" Margin="0">
<
UserControl.Resources>
<
Storyboard x:Name="StatusFader" x:Key="StatusFader" Completed="StatusFader_Completed">
<
DoubleAnimation Storyboard.TargetName="popupBackground" Storyboard.TargetProperty="Opacity" From="0.7" To="0" BeginTime="0:0:0" Duration="0:0:1.5">
<
DoubleAnimation.EasingFunction>
<
ExponentialEase Exponent="10" EasingMode="EaseIn" />
</
DoubleAnimation.EasingFunction>
</
DoubleAnimation>
</
Storyboard>
</
UserControl.Resources>
<
Popup Name="popup" Placement="Center" PopupAnimation="Fade" AllowsTransparency="True">
<
Grid Background="Transparent">
<
Grid Name="popupBackground" Background="Black" Grid.Column="0" Grid.Row="0" />
<
Label Name="popupLabel" DockPanel.Dock="Bottom" HorizontalAlignment="Center" Foreground="White" VerticalAlignment="Center" Background="Transparent" Grid.Column="0" Grid.Row="0"/>
</
Grid>
</
Popup>
</
UserControl>



FadingPopupControl.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;

namespace FadingPopup
{
public partial class FadingPopupControl : UserControl
{
Window ParentWindow { get; set; }
public FadingPopupControl()
{
InitializeComponent();
}

protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
}

public void ShowDialogBox(Window parentWindow, string message)
{
ParentWindow = parentWindow;
popupLabel.Content = message;
Storyboard StatusFader = (Storyboard)Resources["StatusFader"];
ParentWindow.IsEnabled = false;
FrameworkElement root = (FrameworkElement)ParentWindow.Content;
this.Height = root.ActualHeight;
this.Width = root.ActualWidth;
//TODO: Determine why there is 1 pixel extra whitespace.
//Tried playing with Margins and Alignment to no avail.
popup.Height = root.ActualHeight + 1;
popup.Width = root.ActualWidth + 1;
popup.IsOpen = true;
StatusFader.Begin(popupBackground);
}

void StatusFader_Completed(object sender, EventArgs e)
{
popup.IsOpen = false;
ParentWindow.IsEnabled = true;
}
}
}


 


3.) In the MainWindow.xaml, add a Button with a PreviewMouseLeftButtonDown event handler.
4.) Add a local reference and then your popup control.
5.) In your button event handler, initiate the popup.

MainWindow.xaml


<Window x:Class="FadingPopup.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FadingPopup"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"
Title="MainWindow" Height="350" Width="525">
<
Grid>
<
Button x:Name="Test1" Height="40" Width="80" Content="Test1" Grid.Column="0" AllowDrop="False" PreviewMouseLeftButtonDown="Test1_PreviewMouseLeftButtonDown" />
<
local:FadingPopupControl x:Name="popup" />
</
Grid>
</
Window>

MainWindow.xaml.cs

using System.Windows;
using System.Windows.Input;

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

private void Test1_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
popup.ShowDialogBox(Test1, "The is a sample message...");
}
}
}

Screenshots



Fading2


This fades out in 1.2 seconds


Fading

6 comments:

  1. I maybe detected an error. As I recreated your example, which is very useful, it throwed an error in the line "popup.showdialog..." I'm not used to code with C# but as far as I understand the code the first parameter of showdialog should be a window and not the button "test1". So I replaced that with:
    popup.showdialog(this, "The message...");
    and it worked (?=

    ReplyDelete
  2. Anonymous...

    try getting the parent window that the control want...

    see http://viblend.wordpress.com/2011/03/10/find-the-parent-window-of-a-wpf-control/

    and then change:

    popup.ShowDialogBox(Test1, "The is a sample message...")

    to

    popup.ShowDialogBox(GetParentWindow(Test1), "The is a sample message...")

    ReplyDelete
  3. Thanks Claude. Sadly, I have neglected comments as of late.

    ReplyDelete
  4. Set the name in MainWindow.xaml (x:Name="window1") and call the dialog as
    popup.ShowDialogBox(window1, "The is a sample message...");

    BR,

    ReplyDelete
  5. Great control you have here. I've been looking for something like this. Onyl it should open when I click a button and it should only close again when I click a button on the popup.
    Is this doable? Can I modify your contorl to make it work like this? I've been struggling with this for sometime now :(

    Thx for any help or pointers..

    Stieven

    ReplyDelete
  6. it was exactly what i needed. Thanks a lot

    ReplyDelete