A Little Feedback for your article, Dr-Lam!

This is a guest post by Su. Before reading this, I just want you to know that this is not a technical article. This is nothing related to .NET or Silverlight that I used to post in my blog. But As I’m a Buddhist and currently staying in S’pore, I think I should probably post her feedback here. Thanks for sending this post to me, Su!
~ Michael Sync

To whom it may concern, especially Dr Lam and Claire Huang,

I am referring to the article “Doctor with a heart for charitable causes, Page no. A4, My Paper, 26 Mar 2008“. First of all thanks to Dr Lam for his contribution and donation to Myanmar. The level of health condition in Myanmar is low due to low food hygiene standard and people need helping hand like what Dr Lam did. I do appreciate it.

However in the article, Huang quoted “I thought monks, being on a vegetarian diet, should not have coronary heart disease, but I was so shocked to see so many of them with severe coronary heart disease”.

I was originally from Myanmar and lived there since from 1980 to 2001. As a Buddhism. I would like to highlight that most of the Myanmar monks are not vegetarians, not like Chinese monks. To be a Buddhist monk, it is not necessary to be a vegetarian. I don’t think that Buddha himself was a vegetarian. He never set the rule to be a vegetarian in order to be a Buddhist. Some people choose to be vegetarians which came from Hindu. Therefore, vegetarian is “a choice”, not “a must” to a Buddhist.

I would like to ask Dr Lam, why was he so shocked? In fact, they were Myanmar monks and not Chinese monks. Did he ask the monks, who he referred, whether they are vegetarians or not? Were they from vegetarian monastery? What did he mean in that phrase? Why did he choose to put his surprise on Monk, why not Myanmar people?

I was confused after reading that paragraph and worried that it may create misunderstanding about Buddhism in Myanmar and Myanmar Monks to Singaporeans and Non-Buddhists due to tradition and culture difference between Myanmar and Chinese Monks. He may have seen vegetarian monks but they could not represent for whole Myanmar Monk, not vegetarians in majority, although he mentioned “so many of them”.

I would like to request that please leave the perception in Singapore before you comment about other countries.

Regards,
Su

Silverlight 2 (beta1): International (Non-US) TextBox

by Christoph Husse

This is a guest post by Christoph Husse. This is a workaround for the issue #7 of Silverlight 2 (beta1) known issues . Thanks a lot, Chirs!
~ Michael Sync

Download ~

License : MIT-License

1. Introduction

… I was writing a simple logon screen and without any prejudges I tried to enter my E-Mail-Address with my German keyboard… Oh damn what’s this? Silverlight didn’t recognized the “@” char. After some googling I found out why. Silverlight does currently support US-keyboards only. Microsoft, how do you explain this? I mean it’s not hard to support all keyboards; instead it is hard to not support them. Windows by default automatically translates all keyboard codes depending on the user selected keyboard. So it’s simply unknown why Microsoft has dropped support for all other keyboards… Even if portability would be an (cheap) explanation, they didn’t care much about Mono till now, why should they do for Moonlight? I think portability is one thing, to exclude billions of people from using Silverlight sites is another one…

With this little story in mind I wrote a little TextBox supporting my German keyboard and the password chars. For your convenience I decided to use an abstract keyboard class, so any other keyboard may be implemented without much effort. The following shows a simple InternationalTextBox in action:


InternationalTextBox MyBox = new InternationalTextBox();

public Page()
{
InitializeComponent();

MyBox.Keyboard = new German_Keyboard();
MyBox.AcceptTabs = true;
MyBox.Width = 200;
MyBox.Height = 30;
MyBox.Margin = new Thickness(100, 150, 0, 0);
MyBox.HorizontalAlignment = HorizontalAlignment.Left;
MyBox.VerticalAlignment = VerticalAlignment.Top;

LayoutRoot.Children.Add(MyBox);

}

1.1 Support for any keyboard

The main feature is that any keyboard may be used with this component. Currently only the US- and German-Keyboard are supported. But if you look at the source code of those two classes “German_Keyboard” and “US_Keyboard” you will find that it is pretty easy to add your custom keyboard.

You may set the keyboard in the “InternationalTextBox.Keyboard” property. A value of “null” will use the default US-keyboard.

I encourage anyone who got a keyboard not already covered, to write a proper keyboard class and publish it. So we all can take the full advantage of support for any common keyboard layout.

I was really happy to discover, that “Ctrl+v/c/z/y” will work well on my “InternationalTextBox” and even for free…

1.2 Keyboard lists

To work with all of those keyboards, you may enumerate them through “TextBoxKeyboard.Keyboards”. Each of its entries will publish a “Description” that may be shown in a combo-box to the user and a “CreateInstance()”. The latter will allow you to get an object for every keyboard the user selects. You can then directly apply this object to the “InternationalTextBox.Keyboard” property without knowing which keyboard class you are really using…

1.3 Support for typing chars with “Ctrl + [Code]”

Even if windows uses “Alt + [Code]” for the same thing, “Alt” is reserved for the browser and can’t be used in this case. The following picture shows the use of “Ctrl + 9787” which renders a smiley icon…

I’m special.

You may use the “Ctrl” shortcut at any position and you may also use it to replace a text selection.

I think the exact rendering depends on the font selected for the TextBox! Different fonts may produce different symbols for the same control code.

1.4 Password chars

I decided to preset the password char to the one used by windows. You may enable or disable the password chars by setting “InternationalTextBox.IsPassword” to either true or false. Existing text will be converted to circles and circles will be converted to text depending on the current state to switch.

password.JPG

You may select a few circles with the mouse or by holding “Shift” while stepping through the chars with the arrow keys. It is supported to replace such a selection with a new char. The internal password string will be updated appropriate. Of course you may not use “Ctrl+c” for passwords and also “Ctrl+v/z/y” won’t work because they are intercepted by the textbox and would operate on circles only… But I think this is not an issue because passwords shouldn’t be in clipboard.

2 How to derive your own keyboard

Just create a class derived from “TextBoxKeyboard”.

At the beginning you should override the “Description” property and set it to the description used by windows for your keyboard…

Then you have to overload the “HandleKeyDown” method. This is the complicated part. The base class will take care over “Shift”, “Alt” and “Ctrl” states and also supports the direct character input using “Ctrl + ”. So your only duty is to translate the key code to a Char depending on the current keyboard state. To support special chars you may use so called key translation tables:


private KeyToChar[] Default = new KeyToChar[]
{
new KeyToChar() { Code = 220, Char='`'},
new KeyToChar() { Code = 219, Char='-'},
new KeyToChar() { Code = 221, Char='='},
new KeyToChar() { Code = 187, Char=']'},

The “Code” is just the native key code you may determine by setting a proper breakpoint and then pressing a proper key. The “Char” is the value you would expect to appear if the key is pressed. There are three tables. The “Default”-Table is active when none of “Shift”, “Ctrl” or “Alt” is pressed. The “Shifted”-Table is active when “IsShiftDown” is true. The “Alted”-Table is active when “IsCtrlDown” and “IsAtlDown” are true. This emulates the “Alt Gr”-key available on German keyboards for example.

If you use code as shown in the two built-in keyboards, you just have to fill those tables to support your keyboard.

Things will start getting weird if you have to do things like me with the German keyboard. For example if you press the “^” key, it is not written to the TextBox. Instead the keyboard “waits” for the next char. If it is a vocal, the resulting char is either one of “â, ê, û, î, ô”. All other inputs will generate “^[+char]”. But as you can see in the German keyboard class, this is also not very hard to handle…

Updated:

3. Remember user’s keyboard selection

If a user is visiting your site for the first time, he has to select a proper keyboard layout. I recommend to select the US-keyboard by default to be consistent with the current silverlight TextBox. Another option would be to “guess” the layout by interpreting the HTTP-Headers, especially the language. In general the user language will directly map to his keyboard layout. But of course, this is not always the case. I don’t know if Silverlight has any option to directly retrieve the user language. If not, then you have to implement this by using a server side script, and that’s definitely out of scope for my TextBox!

In the following I will just show how such a “remembering” of the user selection may work with Silverlight. You have to change the InternationalTextBox’ instance constructor code to the following. I have to admit that this doesn’t look so pretty…


public InternationalTextBox()
{
KeyDown += new KeyEventHandler(ExtendedTextBox_KeyDown);
KeyUp += new KeyEventHandler(ExtendedTextBox_KeyUp);
TextChanged += new TextChangedEventHandler(
ExtendedTextBox_TextChanged);
SelectionChanged += new RoutedEventHandler(
ExtendedTextBox_SelectionChanged);

try
{
IsolatedStorageFile File = IsolatedStorageFile.GetUserStoreForApplication();

IsolatedStorageFileStream Stream = File.OpenFile("InternationalTextBox.keyboard.layout", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

using (Stream)
{
BinaryReader Reader = new BinaryReader(Stream);
String Selection = Reader.ReadString();

for (int i = 0; i < TextBoxKeyboard.Keyboards.Length; i++)
{
if (TextBoxKeyboard.Keyboards[i].Description.CompareTo(Selection) == 0)
{
m_Keyboard = TextBoxKeyboard.Keyboards[i].CreateInstance();

break;
}
}
}
}
catch
{
m_Keyboard = new US_Keyboard();
}
}

And you have to change the InternationalTextBox’ Keyboard property setter to the following:


set
{
if (value == null)
value = new US_Keyboard();

// copy cap locks and so on...
value.Attach(m_Keyboard);

// register user char event...
value.OnUserChar += new UserCharEventHandler(value_OnUserChar);

m_Keyboard = value;

try
{
// keep this selection in "mind"
IsolatedStorageFile File = IsolatedStorageFile.GetUserStoreForApplication();

IsolatedStorageFileStream Stream = File.OpenFile("InternationalTextBox.keyboard.layout", FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);

using (Stream)
{
BinaryWriter Writer = new BinaryWriter(Stream);

Stream.SetLength(0);
Writer.Write((String)m_Keyboard.Description);
}
}
catch
{
}
}

I didn’t implement this directly because it’s just one of many options to realize “remembering”. The problem with this code is that every time you set the “Keyboard” property, the user’s selection will be overwritten. So you shouldn’t set this property directly, but you may use a ComboBox holding all the supported layouts. If the user explicitly changes the selection of this ComboBox you may also change the “Keyboard” property. I recommend implementing this ComboBox in a way the user is used to by Windows. So simply put a button with a keyboard icon beneath your TextBox. If the user clicks the button, a list containing all possible layouts should appear.

Another approach would be to check weather this file exists and contains a valid selection. If this is not the case you may display an exclusive screen only intended for layout setting. This allows you to force the user to select his keyboard layout before he can do anything on your site, maybe in style of the Windows Vista Account Control Screen.

Silverlight 2 (beta1): URL Referrer, Screen Resolution, Client’s Data Time and IP Address

It’s simple but it’s something that we need to use in the most of projects.

1. How to get the referrer in Silverlight?


var referrer = HtmlPage.Document.GetProperty("referrer");

2. How to get the screen resolution?

I’m not sure whether we have the managed code for that or not. but we can use Javascript to get the screen resolution of the user’s monitor. Please feel free to let me know if you have another approach.


var screenHeight = HtmlPage.Window.Eval("screen.height");
var screenWidth = HtmlPage.Window.Eval("screen.width");

3. How to get the client’s date and time?

Like normal .NET application, we have System.DataTime class in Silverlight.


System.DateTime.Now

4. How to get the IP Address of Client’s machine?

I don’t think that it’s possible to get the IP Address of client’s machine using Javascript or client script. You will need to use the server-side script for that. In my example, I will show the way how to get the IP address in ASP.NET.

The following codes can be used for getting the IP Address or host name but you should note that you won’t be able to get the actual address if the proxy server is hiding those addresses.

  • Request.ServerVariables(“REMOTE_HOST”)
  • HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]
  • HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
  • Request.UserHostAddress()
  • Request.UserHostName()
  • string strHostName = System.Net.Dns.GetHostName();
    string clientIPAddress = System.Net.Dns.GetHostAddresses(strHostName).GetValue(0).ToString();

I will use HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"] in my example. We have to pass this address as parameters to Silverlight content.

4.1. Add asp:Silverlight control in Default.aspx. If you are facing some problems in adding this control, please read this post. Actually, it’s better if we are able to use in TestPage.aspx but we can’t because we want to add <% %> in asp:Silverlight control. As this control is a server control, we can’t add inline server-side code. If you do that, you will get this error “Server tags cannot contain <% … %> constructs”.

4.2. Go to Default.aspx.cs and add the following code in Page_load event.


Silverlight1.InitParameters = "IpAddress=" + HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

4.3. Go to App.xaml.cs and Write the following code in Application_Startup event.


private void Application_Startup(object sender, StartupEventArgs e) {
// Load the main control
string ip = e.InitParams["IpAddress"];
this.RootVisual = new Page(ip);
}

4.4. You need one parameter to the constructor of Page class.

public Page(string ipAddress) {

}

That’s all. This is the way how you can get the IP address of client’s machine.

Additionally, if you want to get the browser information, you can use HtmlPage.BrowserInformation object. Using this object, you will be able to get the version of browser, the user agent and etc.

Hope you will find it useful.

Happy Silverlighting!

Happy Belated Birthday! My Little Blog

Yesterday was my blog’s birthday. My blog is two years old now but still a babe, isn’t it? :) Let’s take a look the stats of my blog and what I have done during last year.

Blog Stats

  • 311, 219 page views this year. ( 377,947 – 66,728)
  • 800 to 2,000 page views per day
  • 97 posts ( 311 – 214)
  • 1342 comments ( 1,961 – 619 )
  • 25 categories

My blogging experience for this year

I moved my blog to Dreamhost on 11st Oct, 07. Their support team is really great.. but there are a few downtime during those days. Another news is that I got two great guest bloggers (Brad McKelvie and egoZd) for my blog recently. Thanks a lot, Brad and egoZd. I hope there will be more guest bloggers who love to share their expertises in my blog. Actually, Guest blogging is “win-win” situation for both blog owners and guest bloggers. I’m really appreciate their help on my blog.

Award

I’ve been awarded SOB (Successful and Outstanding Bloggers) for my blog this year. <link>

Plans for next year.

  • More articles, tip/trick and tutorials for Silverlight: I’ll write more about Silverlight in my blog. And also, I will write about other interesting stuffs some time.

I really want to say “thank you” to all of my loyal readers of this blog. Feel free to let me know if you have any suggestion or comment to improve my blog. Thanks!

Tips/Tricks: Problem in using asp:Silverlight control in Silverlight 2 (beta1)

Someone asked how to use asp:Silverlight control in Silverlight forum. He said that he is getting the error above after adding asp:Silverlight control to ASP.NET project where he host Silverlight content.

Error Screenshot

sl-err.jpg

Solution :

Remove this <system.web><compilation debug=”false”><assemblies>

<add assembly=”System.Web.Extensions, Version=3.6.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″/>

It’s because you have added two different version of System.Web.Extension in your project. The one that you have is 3.5.0.0 but when you place asp:Silverlight control in ASP.NET, the new version (3.6.0.0) will be added in web.config. So, you have to remove this lin.

Happy Silverlighting! :)

Uploading with Silveright 2 Beta 1 and ASMX Web Service

By: egoZd (http://www.douziwang.cn/)

This is a guest post by egoZd who created Tetris game with Silverlight 2 (beta1). As some of you might notice that Brad McKelvie wrote an article about how to upload the file with WCF and Silverlight 2 (beta1) in my blog recently. Now, egoZd shares his idea to use ASMX web service instead of WCF for uploading file in Silverlight. I think it would be useful for those who are not familiar with WCF. (Thank you! egoZd.)

If you guys also like to share some tips/tricks, articles or tutorials, please let me know. ~ Michael

SourceCode Download  : SilverLightFileUploadAsmx.zip

Contents

  • Create Silverlight project
  • Create Webservice
  • Sending the byte array from Silverlight to ASMX web service

Create Silverlight project

  1. Select File->New->Project choose SilverlightApplication
  2. Visual Studio 2008 will automatically create two project ,Web host of the silverlight and silverlight project.

Create Webservice

You can create the Webservice project separately but in this demo, I will create the webservice in the silverlight hosted web project.

1. Select new item to add a new web servcie.asmx file to the host website project.
2. Add a new webmethod .

[WebMethod]
public int GetByteInfo(byte[] abyte, string FileExtention)
{
System.IO.FileStream fs = new System.IO.FileStream(string.Format("C:\\test.{0}", FileExtention),System.IO.FileMode.CreateNew);
fs.Write(abyte, 0, abyte.Length);
fs.Close();
return abyte.Length;
}

Basically, this method is used for receiving the bytes array from Silverlight and will write the file on the server. Note that you should probably change this path to something else that you have the permission to write a file. If you are on Windows Vista, you won’t probably have the permission to write something in C: drive.

Sending the byte array from Silverlight to ASMX web service

1. Add a button control to xaml file


<Button x:Name="btnUplod" Canvas.Left="100" Canvas.Top="130" Content="Please select the file you want to upload" Click="btnUplod_Click" ></Button>

2.Add webservice reference to client silverlight project.

3.Write a upload function for buttion click event.

private void btnUplod_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog OpenFile = new OpenFileDialog();
if (OpenFile.ShowDialog() == DialogResult.OK)
{
ServiceReference1.WebServiceSoapClient client = new SilverLightFileUpload.ServiceReference1.WebServiceSoapClient();
client.GetByteInfoCompleted+=new EventHandler<SilverLightFileUpload.ServiceReference1.GetByteInfoCompletedEventArgs>(client_GetByteInfoCompleted);
Stream s = (Stream)OpenFile.SelectedFile.OpenRead();
s.Position = 0;
byte[] buffer = new byte[s.Length + 1];
s.Read(buffer, 0, buffer.Length);
string Extention = OpenFile.SelectedFile.Name.Substring(OpenFile.SelectedFile.Name.IndexOf('.') +1);
client.GetByteInfoAsync(buffer, Extention);
}
}
void client_GetByteInfoCompleted(object sender, SilverLightFileUpload.ServiceReference1.GetByteInfoCompletedEventArgs e)
{

}

I used a OpenFileDialog to allow the user to select the file. The OpenFileDialog returns the file as a Steam. Then, I converted this steam into a byte array and pass it to web service. My web service will take care of receiving the byte array and create the file on the server. That’s all.

Thanks and Regards,
egoZd (http://www.douziwang.cn/)