Powered by Blogger.

Thursday, January 5, 2012

Tag: , , , ,

Silverlight Overlay Notification

[UPDATE: this blog was moved to a new one]

Welcome back to my blog!

This is the first post of 2012, so just before getting started, I'd like to wish you a happy new year.

Introduction

This time I want to share something very simple for Silverlight. I do not like applications that continuosly bother me with popup messages to make me aware that something happened. I do not like a message box coming up saying "Changes were saved succesfully" right after pressing the save button. I want to keep working or doing some other stuff without being interrupted. I would like to be told that it worked if it allows me to keep going, and of course, I want to know if something went wrong.

You know during Christmas a lot of messages full of best wishes are going around . I sent one of those to one friend and after a while an Overlay Notification appeared at the bottom of my Galaxy's screen saying "Message received by [contact]". Then I realized that this is the kind of notification that I, as an user, like. Therefore, is the kind of notification, that I, as a developer, would like to use henceforth (unless until I find something better :-D ).

The Code

Let us create a User Control. Our control will be the already mentioned Overlay Notification. We'll make it appear and disappear after a while without user interaction. This could be the XAML code:

<UserControl x:Class="SilverlightTestApp.Controls.OverlayNotification"
    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"
    mc:Ignorable="d">
    
    <UserControl.Resources>
        <Storyboard x:Name="ShowMessage" Completed="ShowMessage_Completed">
            <DoubleAnimation
            Duration="00:00:06"
            From="0.00"
            To="1.00"
            AutoReverse="True"
            Storyboard.TargetName="Popup"
            Storyboard.TargetProperty="Opacity"/>            
        </Storyboard>        
    </UserControl.Resources>
    
    <Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Center" >
        <Border BorderBrush="Black" BorderThickness="1" MinWidth="150" MaxWidth="550" MaxHeight="75"
                   CornerRadius="4" Background="Transparent" Visibility="Collapsed" Opacity="0" x:Name="Popup">
            <TextBlock x:Name="lblMessage" HorizontalAlignment="Center" TextWrapping="Wrap" MaxWidth="400" MaxHeight="75"></TextBlock>
        </Border>
    </Grid>    

</UserControl>


We have a Storyboard that will be triggered whenever we want to show the Notification. It will last 6 seconds (plus another 6 because of the AutoReverse=true). And will change the Opacity of our notification area to give the impression that it fades in and out.

Then we have a Border with rounded corners. We'll have to make it visible whenever we want to show the message and hide it when the Storyboard is done. Inside of this Border we will have a Textblock where our message will be displayed.

Let's take a look at the code behind:

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

namespace SilverlightTestApp.Controls
{
    public partial class OverlayNotification : UserControl
    {
        private string _message;
        public string Message
        {
            get
            {
                return _message;
            }
            set
            {
                _message = value;
                lblMessage.Text = value;
                Popup.Visibility = Visibility.Visible;
                ShowMessage.Begin();
            }
        }

        private System.Windows.Media.Color _color;
        public System.Windows.Media.Color Color
        {
            get
            {
                return _color;
            }
            set
            {
                _color = value;
                var newBrush = new SolidColorBrush();
                newBrush.Color = value;
                lblMessage.Foreground = newBrush;
            }
        }

        public OverlayNotification()
        {
            InitializeComponent();
        }

        private void ShowMessage_Completed(object sender, System.EventArgs e)
        {
            Popup.Visibility = Visibility.Collapsed;
        }
    }
}

We will expose at least the Message property (we also have the Color property for the font). Notice that everytime we set the Message property we update the Textblock's text, make the Border visible and trigger the Storyboard. Also noticed that we handle the Storyboard's completed event to hide the Border.

To use it, just add this new User Control into the view where you want to use it in the same way that you would place a Textbox or any other control:

<my:OverlayNotification x:Name="myOverlayNotification"/>

Then, whenever you want to show a Notification, just set the Message property with the message you want to display:

 myOverlayNotification.Color = Colors.Red;
 myOverlayNotification.Message = "This is a test notification";

Final Comments

Feel free to play around with it modifying the layout and appeareance of the control in the XAML or adding more properties to be able to customize it more, for example, adding a BackgroundColor property. Please share your changes in the comments so everybody can learn or use your improvements.
This is just a simple example, but you could also adapt it to use it with the MVVM pattern.

As always, thank you very much for reading. Leave any comment, concern, question or suggestion that you may have.

Hope it helps!






About Nereo Lopez

Hi, this is Nereo. I've spent my first professional years as .Net Software Engineer, and then moved more into Agile Methodologies. Anyway, I keep playing with all the new technologies that appear, and specially love Hybrid Apps!

4 comentarios:

  1. With a bit of styling this works great! One problem, when I combine the codebehind with an MVVM call, it doesn't work. Any idea how to control this from the ViewModel? ty

    ReplyDelete
  2. Hi Mikey, thanks for the comment.

    I would say there are a couple of ways. One would be to bind the User Control to properties in your ViewModel instead, the drawback y that you lose animation. Another possibility (to still have the animation) would be using DataTriggers, I have not tried the code described here, but the idea is correct: http://stackoverflow.com/questions/2548291/mvvm-trigger-storyboard-in-the-view-model-in-silverlight

    If this does not help please let me know. If you find another solution, please share it so I can learn it too :)

    ReplyDelete
  3. I actually decided to keep it in my main page and call it from the child nav Windows
    Frame fm = this.Parent as Frame;
    ChildWindows.OverlayNotification oLay = (ChildWindows.OverlayNotification)fm.FindName("myOverlayNotification");
    oLay.Color = Colors.Purple;
    oLay.Message = "TEST FROM A NavForm!";

    The link you posted gave me an error where
    <ei:ControlStoryboardAction is not found in the Microsoft.Expressions.Interactions.dll. But I will eventually need to call this notification after a WCF Service has completed within the ViewModel

    ReplyDelete
  4. Sorry it did not work. As I said, I did not try the code from the related link. Unfortunatly I have no time due to some projects and studies to play around for a while with it and give you feedback. Maybe you can google a little bit about that topic, I think it is the approach you are looking for, probably you were already close.

    Anyway, If I remember well the link, there was a point when it was talking about binding it to a property in your view model, so, when your WCF call is back, try updating the bound property.

    Regards!

    ReplyDelete