Click here to Skip to main content
Click here to Skip to main content

Silverlight 4: How Can I Create a Customized OOB Window?

By , 27 Mar 2010
 

Introduction

As you all know, Out-Of-Browser functionality in Silverlight is not a new feature. It is available since Silverlight 3. Microsoft added the trusted application behaviour in Silverlight 4 Beta. In addition to this, they introduced one more additional functionality called “Chromeless OOB WIndow” i.e. “Customized OOB Window” in Silverlight 4 RC (Release Candidate). In this post, I will guide you to create a simple customized OOB Window Application in Silverlight 4 RC. After the end of this tutorial, you will be able to create a Customized OOB Window in Silverlight 4 which will look similar to this:

image

Background

Earlier to Silverlight 4 RC, you were able to install the Silverlight application outside the browser Window and could run it from your desktop but there was no choice to customize the look & feel of the Window. From now, it has the feature to create your own Chrome Window to match your application UI. Earlier to Silverlight 4 RC, your OOB application should look like this:

image

Prerequisite

To develop this simple application, you need the following tools installed in your development environment:

  • Visual Studio 2010 Release Candidate
  • Silverlight 4 Release Candidate Tools for Visual Studio 2010 Release Candidate

Remember that, Silverlight 4 applications can be developed only in Visual Studio 2010. Hence, if you have Visual Studio 2008 installed in your PC, you can install Visual Studio 2010 side-by-side for exploring Silverlight 4.

Getting Started

If your development environment is ready, then we can proceed towards creating a new Silverlight Application project. At the end of this part, we will be able to run our first Silverlight application inside the browser.

  1. Open your Visual Studio 2010 IDE
  2. Select File > New Project or just press CTRL + SHIFT + N to open up the New Project dialog
  3. Expand the “Visual C#” node and then go to sub node “Silverlight”
  4. Select “Silverlight Application” in the right pane
  5. Select proper location to store your application (let’s say, “D:\Sample Apps\
  6. Now enter a proper name for your project (call it as: “Silverlight4.OOB.ChromelessWindow.Demo”)
  7. Select the .NET Framework version from the combo box at the top (I am using .NET Framework 4.0)
  8. Click OK to continue
  9. In the next dialog, make sure that “Host the Silverlight application in a new Web site” option is selected
  10. Choose “Silverlight 4” as the Silverlight Version and hit OK

Wait for a while, Visual Studio will now create the Silverlight solution for you to use which will contain a Silverlight Project and one Web Application Project to host your Silverlight application. In your Silverlight project, you will find a “MainPage.xaml” & an “App.xaml” file which are already created for you by the IDE Template.

Design Custom Chrome Window XAML

For our first step, to give a look & feel of a customized window we have to create a “ControlBar” containing the Window Title, Maximize, Minimize & Close button. To do this, let us create a UserControl (for doing this, CustomControl is best rather than UserControl. But I am here using UserControl to give a simple approach for you to understand the main principle) inside the Silverlight project and name it as “ControlBar”.

Here is a simple design of the ControlBar which has a Title as TextBlock, Minimize, Maximize & Close buttons as Border wrapped with Canvas:

<Grid x:Name="grdControlBarRoot" Margin="0,0,0,0">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="15"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="100"/>
    </Grid.ColumnDefinitions>
    <Border Margin="0,0,0,0" Grid.ColumnSpan="3" Background="Black" Height="25"/>
    <TextBlock HorizontalAlignment="Left" Margin="0,0,5,0" VerticalAlignment="Center" 
               Grid.Column="1" Text="{Binding Title, ElementName=userControl}" 
               TextWrapping="Wrap" FontWeight="Normal" 
	      Foreground="White" x:Name="txbTitle" 
               FontSize="12"/>
    <StackPanel x:Name="stpControlBarRoot" Grid.Column="2" Orientation="Horizontal" 
                Margin="0,0,0,0" HorizontalAlignment="Right">
        <Canvas Width="30" x:Name="cnvMinimizeButton" 
		Cursor="Hand" Background="#00000000" 
                	Visibility="Visible" Height="20" ToolTipService.ToolTip="Minimize">
            <Border Width="30" Height="20" Background="#FF939393" 
		BorderBrush="#FF000000" 
                    BorderThickness="1,1,0,1" CornerRadius="0,0,0,5">
                <Border BorderThickness="1.5,1.5,1.5,1.5" CornerRadius="0,0,0,5">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.514,0.623" 
                                             StartPoint="0.514,0.191">
                            <GradientStop Color="#FF828282" Offset="0"/>
                            <GradientStop Color="#FF262626" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <Rectangle Margin="6,9,6,3" Fill="#FFD6D5D5" Stroke="#FF000000" 
                               StrokeThickness="0.5"/>
                </Border>
            </Border>
        </Canvas>
        <Canvas Width="30" x:Name="cnvMaximizeButton" 
		Cursor="Hand" Background="#00000000" 
                	Visibility="Visible" Height="20" ToolTipService.ToolTip="Maximize">
            <Border Width="30" Height="20" Background="#FF939393" 
		BorderBrush="#FF000000" 
                    BorderThickness="1,1,0,1">
                <Border BorderThickness="1.5,1.5,1.5,1.5" 
		      CornerRadius="0,0,0,0" Width="29" 
                        Height="18">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.514,0.623" 
                                             StartPoint="0.514,0.191">
                            <GradientStop Color="#FF828282" Offset="0"/>
                            <GradientStop Color="#FF262626" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <Border Background="#FFD6D5D5" Margin="6,2,6,2" 
			BorderBrush="#FF000000" 
                           	BorderThickness="0.5,0.5,0.5,0.5">
                        <Rectangle Stroke="#FF000000" Margin="2,2,2,2" 
                                   StrokeThickness="0.5">
                            <Rectangle.Fill>
                                <LinearGradientBrush EndPoint="0.5,1" 
				StartPoint="0.5,0">
                                    <GradientStop Color="#FF828282" Offset="0"/>
                                    <GradientStop Color="#FF262626" Offset="1"/>
                                </LinearGradientBrush>
                            </Rectangle.Fill>
                        </Rectangle>
                    </Border>
                </Border>
            </Border>
        </Canvas>
        <Canvas Width="40" x:Name="cnvCloseButton" Cursor="Hand" Background="#00000000" 
                Opacity="1" Height="20" ToolTipService.ToolTip="Close">
            <Border Width="40" Height="20" 
		Background="#FF939393" BorderBrush="#FF000000" 
                    BorderThickness="1,1,1,1" CornerRadius="0,0,5,0">
                <Border BorderThickness="1,1,1,1" CornerRadius="0,0,5,0" Width="37" 
                        Height="16" x:Name="border">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.514,0.623" 
                                             StartPoint="0.514,0.191">
                            <GradientStop Color="#FF956161" Offset="0"/>
                            <GradientStop Color="#FF490E0E" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <TextBlock Text="X" TextWrapping="Wrap" Foreground="#FFECECEC" 
                               HorizontalAlignment="Center" VerticalAlignment="Center" 
                               x:Name="textBlock"/>
                </Border>
            </Border>
        </Canvas>
    </StackPanel>
    <Rectangle Fill="#00FFFFFF" Margin="0,0,0,0" x:Name="rectTitleMask" 
               Grid.ColumnSpan="2"/>
</Grid>

As it is inside a Grid, it can be sized according to the view. The buttons panel has a fixed view & the title section has flexible size. If you watch the above XAML in design view, it will look like the following:

image

Implementing Custom Chrome Window Behavior

Now open the code behind file of the ControlBar.xaml and add a DependencyProperty named “Title” to it, which will be responsible to change the title of the Custom Window.

public string Title
{
    get { return (string)GetValue(TitleProperty); }
    set { SetValue(TitleProperty, value); }
}

public static readonly DependencyProperty TitleProperty =
    DependencyProperty.Register("Title", typeof(string), 
	typeof(ControlBar), new PropertyMetadata(string.Empty));

Now, inside the constructor of the ControlBar class, check whether the application is running Out-of-Browser & has sufficient privileges to run. If so, then set the control visibility to visible and register the button events to fire the minimize, maximize & close events respectively. If the application is running inside the browser, just set the control’s visibility to collapsed and hence no need to register the events.

Here is the code snippet for you:

if (App.IsRunningOOBWithPermission)
{
    this.Visibility = Visibility.Visible;
    this.cnvMaximizeButton.MouseLeftButtonDown += cnvMaximizeButton_MouseLeftButtonDown;
    this.cnvMinimizeButton.MouseLeftButtonDown += cnvMinimizeButton_MouseLeftButtonDown;
    this.cnvCloseButton.MouseLeftButtonDown += cnvCloseButton_MouseLeftButtonDown;
    this.MouseLeftButtonDown += ControlBar_MouseLeftButtonDown;
}
else
{
    this.Visibility = Visibility.Collapsed;
}

Remember that “App.IsRunningOOBWithPermission” is a static property implemented inside the App class and it represents the boolean output of:

((App.Current.IsRunningOutOfBrowser) && (App.Current.HasElevatedPermissions))

There might be a question, what code to be written inside the event blocks? Don't worry, you just have to do the operations as simplest as you can:

void ControlBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    App.Current.MainWindow.DragMove();
}

void cnvCloseButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    App.Current.MainWindow.Close();
}

void cnvMinimizeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    App.Current.MainWindow.WindowState = WindowState.Minimized;
}

void cnvMaximizeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (App.Current.MainWindow.WindowState == WindowState.Normal)
    {
        App.Current.MainWindow.WindowState = WindowState.Maximized;
    }
    else
    {
        App.Current.MainWindow.WindowState = WindowState.Normal;
    }
}

Configuring Out-of-Browser Settings

Now add the “ControlBarusercontrol inside your page and run your Silverlight application. You will find that the ControlBar is not present inside your browser window. This is because it will only be available if we are running the application outside the browser window.

image

Ok, then can we go further to install it outside the browser? Yes, but for this we have to do a few tricks. Go to the properties of the Silverlight project. From the Silverlight pane, select the “Enable running application out of browser” which will make the “Out-of-Browser Settings…” button enabled. Click on it for more settings.

image

From the Settings dialog window, select “Show install menu” which will create a Menu Item inside the Silverlight context menu. Once you run your application and right click on the application, you will see an “Install” menu item on it. I will come to this section later.

Now, check the “Require elevated trust when running outside the browser” as mentioned below and choose “Window Style” as “No Border”. This will make the default Chrome Window visibility to collapsed & if you run OOB, you will not see any Window border by default. Once you are done with this settings, click ok to save the configurations. You can also change the “Window Title”, “Size” and other options available there.

image

Running OOB Application

Now build and run your application which will load inside the browser Window and you will not see any Control bar there as we wrote a code for collapsing the same if running inside the browser. Right click on the Silverlight application. This will show the Silverlight context menu having two menu items “Silverlight” & “Install” inside it. Click the second one to install the application to your local drive as OOB. Once installed, it will automatically run the application out-of-browser window. Now you will see that it has our customized window rather than the default Window border. As we implemented, you can drag the Window from the Title Bar, minimize, maximize & even close the Window using our controls.

image

End Note

As I mentioned earlier, it is a simple approach to customize the OOB Window in Silverlight 4. Now you can implement more functionalities like resize, border thickness, animations & styles, etc. to solve your business needs. Again, it is better to implement it as a Custom Control instead of User Control and that will give you more power on each section. Go ahead and enjoy this new feature.

You can download the Sample Project: Customized Silverlight 4 OOB Window

History

  • 27th March, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

_ Kunal Chowdhury _
Software Developer
India India
Member
Kunal Chowdhury is a Microsoft MVP (Most Valuable Professional) in Silverlight Technology, a Codeproject MVP & Mentor, DZone MVB (Most Valuable Blogger), Speaker in various Microsoft events, Author, passionate Blogger and a Software Engineer by profession.
 
He is currently working as a Software Engineer II in an MNC located at Pune, India. He has a very good skill over XAML, C#, Silverlight and WPF. He has a good working experience in Windows 7 application (including Multi-touch) development too.
 
He posts his findings in his technical blog. He also writes for SilverlightShow and Codeproject portal. Many of his articles were highlighted as "Article of the Day" in Microsoft sites.
 
He also has another website called Silverlight-Zone.com where he posts article links on Silverlight, Windows Phone 7 and XNA accumulated from various web sites to help the community grow on specified technologies.
 
You can reach him in his Blog : http://www.kunal-chowdhury.com
He is also available in Twitter : http://twitter.com/kunal2383

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberMember 30144108 Nov '10 - 20:13 
It was on-time guide
GeneralMy vote of 4memberEric Xue (brokensnow)4 Sep '10 - 13:02 
keep up with your good work!
AnswerRe: My vote of 4mentorKunalChowdhury4 Sep '10 - 15:32 
Hi Eric,
 
Thanks for your support. I answered your query here. Let me know, if you need any more information.

 
Don't forget to Click on [Vote] and [Good Answer] on the posts that helped you.


Regards - Kunal Chowdhury | Software Developer | Chennai | India | My Blog | My Tweets | Silverlight Tutorial

QuestionWhy do you use an empty "catch"?memberEric Xue (brokensnow)4 Sep '10 - 13:00 
As always, your article for silverlight 4 series is the highlight of my readings. But I do pick up some interesting coding practice in your example code then hope you can shed some light on?
 
private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
{
try
{
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
 
System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
}
catch (Exception)
{
}
}
 
As the codes shown above, obviously there is no catch handling logic in the exception throw block and thereby, could you please let me know why you handle that by your codes above?
 
Sorry for my ignorance but the approach you applied on that doesn't seem to be a good coding practice aligning with my coding standards. So maybe you can walk me through with that.
 
In addition to that, if you can do a quick null check on e.ExceptionObject, you wouldn't need to have that try and catch block after all, right?
 
if (e.ExceptionObject != null){
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
 
System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
}else{
System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application for null reference in e.ExceptionObject."\");");
}
AnswerRe: Why do you use an empty "catch"?mentorKunalChowdhury4 Sep '10 - 15:30 
Hi Eric,
 
Thanks for reading my articles and providing feedback.
First of all, I will ask you one question: "Are you new to Silverlight?"
 
Yes, if you are new to Silverlight, then only you can ask this question.
And the code above you pointed is not written by me. It generates automatically by the Visual Studio IDE whenever you create a new Silverlight Application and it resides in the App.xaml.cs file. So, ask this to Microsoft, why they are not following proper coding practices... Laugh | :laugh:
 
Ok, I think you are new in Silverlight. So, let me answer your queries:
 
Eric Xue (brokensnow) wrote:
As the codes shown above, obviously there is no catch handling logic in the exception throw block and thereby, could you please let me know why you handle that by your codes above?

 
The code is not written by me. It generates automatically by the IDE whenever you create a Silverlight application. Reason behind this is, if you want to do some exception handling or error logging, you can do it here (application level). We code here for production level applications.
 
Eric Xue (brokensnow) wrote:
Sorry for my ignorance but the approach you applied on that doesn't seem to be a good coding practice aligning with my coding standards.

 
Report this to Microsoft.... Shucks | :->
 
Eric Xue (brokensnow) wrote:
In addition to that, if you can do a quick null check on e.ExceptionObject, you wouldn't need to have that try and catch block after all, right?

 
Again, ask Microsoft "Why they didn't do it?"
 
Let me give you some basic pointers on it.
 
The code System.Windows.Browser.HtmlPage.Window.Eval may throw you another Exception if something wrong in the plugin level for the application. In such case the exception should silently handle by it. As it is in Application level unhandled_exception block, you can't escape and return back to your application. Silently handling it will work fine here.
 
I am quite sure that, you are new in Silverlight (or, you didn't explore the App.xaml.cs file earlier), because this code is always there in Silverlight. Please read some good tutorials on the technology. Also, read the Silverlight Tutorial written by me. That will give you some basic idea.
 
Thanks for your feedback. Keep reading... Keep learning... Cheers... Smile | :)

 
Don't forget to Click on [Vote] and [Good Answer] on the posts that helped you.


Regards - Kunal Chowdhury | Software Developer | Chennai | India | My Blog | My Tweets | Silverlight Tutorial

AnswerRe: Why do you use an empty "catch"?memberEric Xue (brokensnow)4 Sep '10 - 16:08 
There you go. My bad! Thanks for your speedy response.
QuestionYour download link for the project doesn't work?memberTV Mogul21 May '10 - 0:01 
Your download link for the project doesn't work?
http://www.KabbalahCode.com

AnswerRe: Your download link for the project doesn't work?mentorKunalChowdhury21 May '10 - 0:14 
Hi TV Mogul,
 
Download link works. Once downloaded, just remove the "_" (underscore) from the end of the file. It will become a .ZIP file. Then you can extract it.
 
Let me know, if you have any issues.
Don't forget to Click on [Vote] and [Good Answer] on the posts that helped you.


Regards - Kunal Chowdhury | Software Developer | Chennai | India | My Blog | My Tweets | Silverlight Tutorial

GeneralYour link does NOT exist !!!!memberTV Mogul21 May '10 - 3:56 
Hi,
 
I tried clicking on the download link for the project in 3 different browsers--go ahead and try it and NOTHING !!!!
 
The link on teh page goes nowwhere and you can't download anything!!!!
 
Bill
http://www.KabbalahCode.com

AnswerRe: Your link does NOT exist !!!!mentorKunalChowdhury21 May '10 - 5:34 
Hi Bill,
 
I checked it in both IE 8 & Firefox 3. In both the cases it is working fine. Once you click, it will go to the Windows Live SkyDrive. There you will find a link called "Download". Click that. You will be able to download it.
 
Let me know, if any issue. In that case, share me your email id. I will be happy to send it by mail.
Regards - Kunal Chowdhury | Software Developer | Chennai | India | My Blog | My Tweets | Silverlight Tutorial

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 27 Mar 2010
Article Copyright 2010 by _ Kunal Chowdhury _
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid