How to handle multiple global constants in an application

The best way to have something organized and having constants in a single place is to have a class that will have inner class. This way, you can organize by theme your constants.

public static class GlobalConstants
{
	public static class Division1
	{
		public const string Const1 = "123";
		public const string Const2 = "qwe";
		public const string Const3 = "asdfgh";
	}

	public static class Division2
	{
		public const string Const1 = "123";
	}
}

Of course, it’s always better to have your constant in the class that they are more related. For example, the default value for a specific property of a class should be directly inside this class. But, for global constants that are used across the application, than having a global constants class can do the job.

How to do a hit test with Point and Shape?

In some situation, you may need to know if the mouse has hit a specific polygon drawn in a canvas. This can be easily done with Silverlight using the VisualTreeHelper.

First of all, you need to have a listener to the mouse even.

 void myCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
	e.Handled = true;
	Point currentMousePosition = e.GetPosition(this.myCanvas);
	var underMouseControls = GetControlFromCoordonate(currentMousePosition);
}

The second step is to create the method GetControlFromCoordonate to return a list of Control that has been clicked.

public IEnumerable<Control> GetControlFromCoordonate (Point coordonate)
{
	return VisualTreeHelper.FindElementsInHostCoordinates(coordonate, this.myCanvas).OfType<Control>();
}

This will return an enumeration of all UIElement which be cast to have only Control. You can even filter more if you search specific control.

So, the VisualTreeHelper may not have a HitTest method but with the FindElementsInHostCoordinates, you can filter the result to have the same result.

Installing Silverlight 2 on Visual Studio 2008 without getting the event log file is full error

The event log file is full error

This is what I was getting the day I had to install Silverlight 2 on a Visual Studio 2008 software. I have Visual Studio 2010 working with Silverlight 4 but this project is older and required to have a previous version of C# and Silverlight.

I got told to install the Silverlight 2 Tool for Visual Studio 2008.

This tool is 74.4 megs and named Silverlight_tools.exe which can be found on Microsoft web site.

So far, all is straight forward and the installation is a Wizard that will require you to close all Microsoft Internet Explorer instance and all Visual Studio (2008 and 2010).

The problem come when installing. An error can occur saying that the Event Log file is full.

You can have the detail of the error by clicking View the Log File. This will open a browser where you can see all the installation trace.

This is where something need to be done which is not clear. First we may think to clear the Windows Event Log. This can be done by selecting one by one all Log category. Select properties and Clear log.

You can see when the logs are cleared if you come back into the screen. You will see that the size of each categories are now really low if not zero.

Even before clearing the log I was pretty sure that wouldn’t solve the problem because all my logs properties had the feature to erase old log if space was required.

As I believed, the error was still there with the same message.

My second thought was to download the Microsoft Silverlight 2 SDK which seem not to be there on my computer. I had the 3 and the 4 but not the 2. This file is still available on Microsoft Website and is smaller than the Microsoft Tool with 50.2 megs.

The installation was successful.

But, still couldn’t load the Silverlight project for Visual Studio 2008. I decided to run again the Silverlight 2 Tools kit but without much success.

This lead me to go back into the Microsoft Event Viewer to see what happen since the clean up. I had few entries since I had try to install the Tool package once before installing Silverlight 2 SDK and one other time after. The log is not in error but contain a link to the Html log that contain the message with the error. I also noticed that SPInstaller is not available.

This haven’t gave me any other idea than cleaning the %TEMP% folder but doesn’t give any better result.

So I decided to give a try by searching on Google.com “Microsoft Silverlight Tools for Visual Studio 2008 SP1”. Maybe their some other tools for Visual Studio 2008. I got a surprise to see that Visual Studio 2008 does have a tools for Silverlight 3. I give it a try and at my big surprise, see the installation getting a lot longer.

After 10 minutes, the installation was successful.

I decided to give a try to the solution which needed to load the Silverlight project.

And this time it worked!

To fix this error, I had to install Silverlight 3 Tools.

Localized Silverlight with Resource File

Let say that you want to have your application in multiple language. In Asp.Net, the choice is obvious to go with resource file. Since I am coming from the web side, I did the same thing with Silverlight.

Visual Studio Resource Editor

In Silverlight, you can still use Resource File. They are available in the New Item dialog.

How to add a Resource file to Silverlight

In my project I added two resources file : MyRes1.resx and MyRes1.fr.resx. This way, I can have English and French words translated.

The next logical step is to handle the language selection. In my case, the language came from the Asp.Net page. It was passed as a parameter. In App.xaml.cs, in the Application_Startup() event, I added a call to SetCultureInformation() which I have defined like this:

private void SetCultureInformation(StartupEventArgs e)
{
	var languageInfo = new CultureInfo("en");
	if (e.InitParams.ContainsKey("language"))
	{
		if (e.InitParams["language"] == "fr")
		{
			languageInfo = new CultureInfo("fr");
		}
	}
	
	Thread.CurrentThread.CurrentCulture = languageInfo;
	Thread.CurrentThread.CurrentUICulture = languageInfo;            
 }

I were ready to execute to test but I had the problem that Silverlight didn’t want to switch to French.

After few hours, I realized that Silverlight’s project can have specific variable to be set to be able to tell Silverlight which language is supported.

To do, open your Silverlight project with Notepad and search for “SupportedCultures”

SupportedCultures

You need to set all language you want, but no need to add the default one. In my case, I added only the French one, so “fr”.

After that, everything worked.

How to add animated effect to UIElement.Effect

If you want to make glowing a shape with Silverlight without having to use Xaml it’s possible. At first, I thought it was impossible because I were using a third-party object that use their own type of Shape. After reading the property I figured out that the Effect property was exposed. This let us use System.Windows.Media.Effects.

To make it looks glowing, I decided to use the DropShadowEffect which can have a blurry shadow.

    var errorEffect = new DropShadowEffect { BlurRadius = 50, Color = Color.FromArgb(255, 255, 0, 0), Direction = 0, ShadowDepth = 0, Opacity=1};

This create the blurry effect because the ShadowDepth is at 0 and the BlurRadius somehow high.

The problem is that I wanted it to fade it and fade out which wasn’t possible without using StoryBoard. I also thought that it was impossible cause the shape didn’t have any story board or animation property. I was wrong.

It’s possible to use the static method of the StoryBoard class to set an animation or many animation to an object.

Here is two ways to make the shape going on and off.

 var shadowOpacityAnimation = new DoubleAnimationUsingKeyFrames
                                         {
 
                                             Duration = new Duration(TimeSpan.FromMilliseconds(10000)),
                                             RepeatBehavior = RepeatBehavior.Forever,
                                             AutoReverse = true
                                         };
            shadowOpacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = new TimeSpan(0,0,0,0), Value = 0 });
            shadowOpacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = new TimeSpan(0,0,0,1), Value = 1 });
            shadowOpacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = new TimeSpan(0,0,0,7), Value = 1 });
            shadowOpacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame { KeyTime = new TimeSpan(0,0,0,10), Value = 0 });
            Storyboard.SetTarget(shadowOpacityAnimation, myShape);
            Storyboard.SetTargetProperty(shadowOpacityAnimation, new PropertyPath("(UIElement.Effect).(DropShadowEffect.Opacity)"));

This way let you use key frame which are some time mark where you can set value. In the above example, I set the total animation time to 1000 milliseconds and make it repeat forever. I also specify that I want the animation to go on to off, and off to on with the AutoReverse to True. I after that add 4 time marks which set the opacity to 0 and will fade in for 1 second to the maximum opacity value : 1. Then, I wait from 1 second to the 7th second with full opacity before going down to 0.

The last two line tell to set the animation target to my shape. In that case, I were setting the shadowOpacityAnimation to myShape. The last one specify which property of myShape I will change. This can be a little bit more tricky. If you have blend, it’s a good time to fire it up and check the generated Xaml. Otherwise, do not worry, it’s logic.

You need to create a PropertyPath which will tell what property to change.

...  new PropertyPath("(UIElement.Effect).(DropShadowEffect.Opacity)") ....

In my case, I want to change the Opacity of the DropShadowEffect which are in the Effect of my objec that inherit this method from UIElement. As you can see, you have to write the sequence in reverse and you are done.

If you want to make it glows without using opacity, you can also do it with the BlurRadius property.

  var blurRadiousAnimation = new DoubleAnimation
                                       {
                                           From = 50,
                                           To = 0,
                                           Duration = new Duration(TimeSpan.FromMilliseconds(2000)),
                                           RepeatBehavior = RepeatBehavior.Forever,
                                           AutoReverse = true
                                       };
            Storyboard.SetTarget(blurRadiousAnimation, addFlowShape);
            Storyboard.SetTargetProperty(blurRadiousAnimation, new PropertyPath("(UIElement.Effect).(DropShadowEffect.BlurRadius)"));

In that case, it’s simpler. We do not use key frame but simply a DoubleAnimation that will go from one value to another. This one is changing the BlurRadius every 2 seconds.

In both case, you need after to add the animation to the story board and to start it.

  var stb = new Storyboard();
            stb.Children.Add(shadowOpacityAnimation);
            stb.Children.Add(blurRadiousAnimation);
            stb.Begin();

In that case, I have added both animation. Yes, you can add more than 1 animation per object. Do not forget to use the Begin() method and you will be all set.

Silverlight exception with javascript “failed to invoke” when using HtmlPage.Window.Invoke

Silverlight can interact with the Javascript that reside in the page that this one is hold. We have seen in the Silverlight Communication post that it’s possible with the use of System.Windows.Browser.HtmlPage.Window.Invoke.

Sometime, an exception can be thrown with the title “InvalidOperationException was unhandled by user code”. The troubleshooting tips should contain something like “Failed to invoke”.

InvalidOperationException was unhandled by user code

In fact, what happen is the Javascript is throwing an error. It can be any errors not catch in the Javascript. So, when you get this error, the best thing to do is to launch a Javascript Developer tool (for example F12 with Internet Explorer) and activate the Script Debugging functionality. When an error will be thrown and not catch, the tool will break and you will be able to change your script.

How to localize Silverlight Application with Resource File

Having your Silverlight application in multiple language is pretty the same as ASP.NET localization mechanism.

The first step is to create a new Resources File for your default language (English is the default one). You will find the Resources File template in the “Add New Item” under General tab.

Add a Resources File in Visual Studio 2010

Once it’s done, you can repeat that task for other language. Like with ASP.NET, you need to change the file name to have the two letters acronym of the language.

Two Resources Files

The second part is to add string into it. Simply double click the file and add Name and value for the string you want to be localized.

The last step is to use those values. To do it, simply use the code that has been generated by Visual Studio under the resource file (.designer).

var errorCaption = ErrorMessages.CaptionEmpty;

And that’s it, you have now inside errorCaption your localized string.

Silverlight communication with Javascript

You may have some situation that you need to communicate with the page that your Silverlight reside.

This can be done by three methods:

  • Passing parameter to Silverlight
  • Silverlight call a Javascript method of your page
  • The Javascript call a Silverlight method

Silverlight parameter

All Silverlight application contain a startup method that has a StartupEventArgs. This class has a InitParam dictionary (IDictionary) that contains all parameters.

private void Application_Startup(object sender, StartupEventArgs e)
{
   if (e.InitParams.ContainsKey("debug"))
   {
        Debug.WriteLine(e.InitParams["debug"]);
   }
}

To pass parameters you need to add in the html a new element with the attribute name “initParams”.

<div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
		  <param name="source" value="ClientBin/MyProject.xap"/>
		  <param name="onError" value="onSilverlightError" />
		  <param name="background" value="white" />
		  <param name="minRuntimeVersion" value="4.0.50826.0" />
		  <param name="autoUpgrade" value="true" />
		  <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
 			  <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
		  </a>
          <param name="initParams" value="debug=false, secondParameter=2 " 
          />

	    </object>
        <iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>
</div>

As you can see in this example, if you need more than one parameter you need to use a comma between all parameter. The value is automatically a string. You will need to parse it to the desired type inside Silverlight.

Silverlight communicate with Javascript

The communication between Silverlight and Javascript is straight forward. You need to use the Invoke method of HtmlPage.Window.

System.Windows.Browser.HtmlPage.Window.Invoke("MyFunction", "Parameter1");
System.Windows.Browser.HtmlPage.Window.Invoke("MyFunction", "Parameter1", "Parameter2");

The invoke method has a params[] for its second parameter. That let you add has many parameter value that the function in Javascript require.

public virtual object Invoke(string name, params object[] args);

Javascript to communicate with Silverlight

Javascript can also call method inside a Silverlight application. To do, you need to first declare an entry point name.

System.Windows.Browser.HtmlPage.RegisterScriptableObject("Page123", this);  

This code can be added at the beginning of the constructor of the method that will be called. It specifies a unique identifier that will be used in the Javascript.

The second thing that need to be done inside Silverlight is to add an attribute to the method that you want to expose to the external.

[ScriptableMember]
public void JavascriptWillCallThisMethod(string textFromJavaScript)
{
    Debug.WriteLine(textFromJavaScript);
}

The third and last step is to call this method from the Javascript code.

 var control = document.getElementById("silverlightControl"); 
 control.Content.Page123.JavascriptWillCallThisMethod("Hello from Javascript!");

As you can see, you find the “Page123” again here. It’s the name declared in the Silverlight application when calling the RegisterScriptableObject method.

How to debug Silverlight application with only XAP file?

Sometime, when the application is deployed to IIS server you may still need to do some debugging. Debugging a Silverlight application is in fact very easy, and pretty much the same when you are working inside Visual Studio but change when you need to debug it on the server.

The first step is to be sure that you .xap file deployed on IIS is the same as the one that you have in your developer environment. This can be automated when a Post-Build condition like this:

copy $(TargetDir)YOURxapFILEname.xap c:\wwwroot\mywebsite\ClientBin\YOURxapFILEname.xap

The second step is to go in Debug menu of Visual Studio and choose Attach To Process. This is a step that you would have to do to debug ASP pages. But, this will require a modification. When debugging .Net code, you usually set your debugging type to Managed. In the case of Silverlight, you must select Silverlight. This will automatically popup you a message saying that you cannot continue to debug in Managed. Just accept.

The debugging type must be Silverlight

The third step is to attach to the process. This also require a modification. When debugging a ASP page you usually select W3WP.exe (the IIS application pool). This time, you need to attack to your browser. This can be Internet Explorer, Firefox or Chrome. The reason is that Silverlight is not server side but client side.

You must attach to the browser, not IIS

From there you just need to refresh your page and the breakpoint you have set will be trig once reached.

How to clone with Silverlight without ICloneable?

The .Net Framework allow to clone ICloneable interface. This interface has a single method that is Clone. This interface is not available in Silverlight. The reason is that Microsoft have found that since it does not provide specification between deep copy or shallow copy that it was useless to port this interface into the Silverlight SDK. In fact, this interface has been questionable since a long time ago.

An other way to clone is to serialize and deserialize your object. By using this mechanism all references are not there but the value are. The problem, is that Silverlight does not have the System.Runtime.Serialization has you may know in the .Net standard framework. You won’t fine the the IFormatter interface neither the BinaryFormatter class.

So, how to clone an object in Silverlight?

Here is a cloning method that is an extension for every object. It uses reflection to do it’s cloning. This is not a deep copy!

public static class CloningExtension
{
    public static T Clone<T>(this T source)
    {
        T cloned = (T) Activator.CreateInstance(source.GetType());
 
        foreach (PropertyInfo curPropInfo in source.GetType().GetProperties())
        {
            if (curPropInfo.GetGetMethod() != null && (curPropInfo.GetSetMethod() != null))
            {
                // Handle Non-indexer properties
                if (curPropInfo.Name != "Item")
                {
                    // get property from source
                    object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});
 
                    // clone if needed
                    if (getValue != null && getValue is DependencyObject)
                        getValue = Clone((DependencyObject) getValue);
 
                    // set property on cloned
                    curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
                }
                    // handle indexer
                else
                {
                    // get count for indexer
                    int numberofItemInColleciton =(int)curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});
 
                    // run on indexer
                    for (int i = 0; i < numberofItemInColleciton; i++)
                    {
                        // get item through Indexer
                        object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});
 
                        // clone if needed
                        if (getValue != null && getValue is DependencyObject)
                            getValue = Clone((DependencyObject) getValue);
                        // add item to collection
                        curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
                    }
                }
            }
        }
 
        return cloned;
    }
}

If you want more information you can read this forum thread.