woensdag 16 maart 2011

Build your own silverlight in browser toast

Build your own in browser toast
Toast can be very handy tools that allow you to notify the user of an event that happened without blocking him.  However it’s a shame that toast aren’t available when running your application in browser.  Off course it is understandable that toast can’t provide the full use within the user’s browser, although in some cases this could prove useful.   Image the user downloading a file from your server and you wish to notify him when the download is finished.  Or some operation is finished or an event is raised in another page.  Then toasts can be very useful.
In this example I will be using a navigation application.  The reason why I do this is because then we can define our ‘toast’ in the mainpage and it will be a level higher in the hierarchy than the pages.  We aren’t really going to be using a toast but a popup that will behave like a toast.  Here is the code:
In our MainPage.xaml we define the popup and a corresponding storyboard that will make the popup show up and down:
    <UserControl.Resources>
        <ViewModels:MainViewModel x:Key="vm"/>
        <Storyboard x:Name="PopupStoryBoard">
               <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.VerticalOffset)" Storyboard.TargetName="popup">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="-60"/>
                <EasingDoubleKeyFrame KeyTime="0:0:3.2" Value="-60"/>
                <EasingDoubleKeyFrame KeyTime="0:0:4" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}" Background="{Binding}" DataContext="{StaticResource vm}">

Some other code can come here…  

    <Popup x:Name="popup" Width="auto" Height="auto" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Bottom" VerticalOffset="0"
               DataContext="{Binding PopupViewModel}" IsOpen="True">
               <!--Visibility="{Binding RelativeSource={RelativeSource self}, Path=DataContext.Show, Converter={StaticResource VisibilityConverter}}">-->
            <Border Name="popupBoder" Width="auto" BorderThickness="1"
                    BorderBrush="{StaticResource BaseBrush7}"
                    Background="White">
                <TextBlock Text="{Binding Text}" FontSize="12" Margin="10"/>
            </Border>
        </Popup>
    </Grid>

</UserControl>

We can then define a viewmodel for the Popup.  For simplicities sake, we will make this a singleton.
Imports ePostbus.ViewModels.Base

Namespace ViewModels

    Public Class PopupViewModel
Inherits ViewModelBase

        Private _show As Boolean
        Private _text As String
        Private Shared _instance As PopupViewModel

        Public Shared ReadOnly Property Instance As PopupViewModel
            Get
                If _instance Is Nothing Then
                    _instance = New PopupViewModel
                End If
                Return _instance
            End Get
        End Property

        Public Sub Show()
            If ShowAction IsNot Nothing Then
                ShowAction.Invoke()
            End If
        End Sub

        Public Shared Property ShowAction As Action

        Public Property Text As String
            Get
                Return _text
            End Get
            Set(value As String)
                _text = value
                RaisePropertyChanged(Function() Me.Text)
            End Set
        End Property

        Protected Overloads Sub RaisePropertyChanged(Of propertyToInvoke)(ByVal expression As Expression(Of Func(Of propertyToInvoke)))
            Dim body = TryCast(expression.Body, MemberExpression)
            If body Is Nothing Then
                Throw New ArgumentException("'expression' should be a member expression")
            End If

            Dim propertyName As String = body.Member.Name

            MyBase.RaisePropertyChanged(propertyName)
        End Sub

    End Class
End Namespace

Al we than need is to initialize our ShowAction so we can play the storyboard when needed:
        PopupViewModel.ShowAction = Sub()
                                        Dim storyboard = TryCast(Me.Resources("PopupStoryBoard"), Storyboard)
                                        storyboard.Begin()
                                    End Sub

I putted this blogpost in VB.NET, so I don’t discriminate anyone ;)
Have fun…

Geen opmerkingen:

Een reactie posten