Tuesday, March 16, 2010

Resolution Independent Layout Fix in WPF

It is very important to keep track of Operating System Resolution while building one application. We do lots of things to make the application work the same way in various ranges of Operating System Resolutions. For WPF developers, it is quite obvious to miss out the Anchor and Dock properties, which is present in Windows Applications but quite annoyingly absent here. The result of this is, when we change the Resolution of the Display, the UI of the application gets waked up abruptly.


"Oh god, how can I solve the same problem once again" --- This is what I thought after I built a brand new application altogether tested it in various Resolutions that is supported in my machine, and saw that it just didn't worked in a machine of one of my colleague. Well, even I thought of changing the machine resolution to something that suits my application and revert it when application closes ( Just like what DirectX games does).

The idea was good, but this would slow down performance, and also make other programs running in the windows unusable. I was very worried for the last couple of days, until today, I found a way of eliminating the problem using ViewBox.

While development of UI, I always liked to avoid ViewBox, as ViewBox generally changes the normal behavior of the UI elements. But strangely enough, I found that is the only way to make the UI look the same in all other Resolution possible.

<viewbox stretch="Fill">  <grid width="600"> Height="800">  </grid></viewbox>

Using ViewBox makes it Resolution Independent

If you see this minutely, the UI is same as we do normally, but I just wrapped around the existing UI with a ViewBox with Stretch property is set to Fill. Thats all, you need.

You can check the UI in different Resolution, and I bet, it will look the same way in all.

Points to Remember

You should remember to create the UI with the resolution for which the chances of getting it is the most. Say you think you will have more customers using 1024 x 768 than 1400X900, then it is recommended to set the height and width of the Grid inside the viewbox with this. Actually, ViewBox stretches the existing UI to fill up the space. This might sometimes create the UI look hazy. So more and more dispersed Resolution than the mean, will lead to more and more unclear User Interface. As the ViewBox will stretch the existing UI from the original content, so it is always good to choose a resolution which is very common to users.

Another point is while using ScrollViewer inside your grid, please ensure you specify the Height of it. In fact if ViewBox finds a ScrollViewer inside it without height specified, it will shrink the existing control directly without scroll bar being generated. This would look weird, so please take care of it.

Try out the Sample Application

Download Source


READ THE FULL ARTICLE

Sunday, March 14, 2010

How to use IValueConverter in Binding of WPF

 In this article I am going to discuss about how we can use Converter to evaluate the Binding of elements in WPF. All of us are well aware of superior Binding Capabilities that is supported with WPF. I found it very exciting when I saw it for the first time. It seemed to me a great way to define everything in XAML rather than handling events so much in Code-Behind. Right now, I try everything that regards to UI level changes, I always try to do it using XAML first.

XAML comes with lots of Markup Extensions. Anything that is placed within the curl braces ( { } ) are defined as Markup Extensions. They are derived from the Class MarupExtension, and the properties are defined directly for them within the brackets. Binding is also a Markup Extension for which ElementName, Path, etc are members. Among the members, Converter and ConverterParameter is what we are going to discuss here in this article.

IValueConverter

Converter is actually a property within the Binding Markup Extension. Its type is defined as IValueConverter. Every time the bound data elements refreshes its value it passes through a method Convert which is defined inside the object Converter (if found). Thus Converter acts as an interface to manipulate the actual data before passing it to the property.
public class MyConverter : IValueConverter
{
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            double passedValue = (double)value;
            double parameterValue = (double) parameter;
            return passedValue - parameterValue;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            
            double passedValue = (double)value;
            double parameterValue = (double)parameter;
            return passedValue + parameterValue;
        }

        #endregion
}
Here in the code above I have defined a converter MyConverter, which does nothing but implements IValueConverter, which enables you to make use of it with Converter. The Converter here does nothing but implements two methods, Convert and ConvertBack. Convert is called when the value of the property is updated when the bound object value is changed. ConvertBack will only be called when the Binding Mode is set to TwoWay, and will be called only when the bound property changes its value.  The object value points to the value of the property passed in, TargetType is the type you have to return to the Target, parameter is defined from ConvertParameter and Culture is the UICulture.


To use the Converter you need to create a resource of the object. Thus in XAML you need to declare :

<local:myconverter x:key="resMyConverter">
</local:myconverter>

Where local is the namespace added which points to the Current Namespace. Finally to define the Converter, you need to use this as StaticResource in the Converter.

Height="{Binding ElementName=win, Path=ActualHeight, Mode=OneWay, Converter={StaticResource resMyConverter}, ConverterParameter=10}"  

Remember one thing, in the above line, you need to make sure you are clear about what you are sending. In this case, we are binding Height with the ActualHeight of the element win. So, in the arguments of Convert, you will receive a double value with current ActualHeight, and you are going to return the value that you want to be set to Height. So actually you are sending a double value and returning another.

The above figure demonstrates how you are going to send data to Convert method.The ActualWidth (Marked with Blue) is sent to object value, TargetType will be Double which is based on the Type of Width Property, parameter receives the value 50 passed with ConvertParameter, and the culture is the UICulture of the Current Thread.

The ConvertBack is used to be called only when you need the reverse. So if your Mode is defined as OneWay, your ConvertBack is not actually required.

You can try the sample application from here

Read the Full Article

Thursday, March 11, 2010

Another article Published @WindowsClient.net

It is always nice to see an article published in Windowsclient.net. And if it happens so quickly, it is even better. I have just demonstrated the use of Multilingual applicaiton using WPF. It is just the login screen, where you can give user id and password. The static elements are fetched from Resource files.

The figure in the right shows how the UI looks like, when you run the application. The static elements are dependent on the Current UI culture. If we make the current regional settings as French, the UI elements will look as french.

The resources will be loaded dynamically using Thread.CurrentThread.CurrentCulture.

You can read the complete article from

Simplest Way to Implement Multilingual WPF Application



I would also like to Congratulate all my followers, Mr Sheo Narayan, Abhijit Jana, who always appreciated my work all the time.


Thanks for reading.

Sunday, March 7, 2010

“Article of the day” @ Microsoft’s official website www.windowsclient.net

Guys, I am very thankful to Mr Sheo Narayan (The Founder of DotNetFunda), and Dotnetfunda team, to nominate my article to be published in MS Official Site www.windowsclient.net.




Today, it is selected as "Article of the Day" in the site. The article is describes how we can implement Asynchronous Call to methods using Delegates. I have used BeginInvoke and EndInvoke which implicitly creates a new Thread from ThreadPool and invokes the method.

You can see the article from here. Dont forget to put your feedback.


Asynchronous Method Invocation

Multilingual Application using WPF

Creating a multilingual application using WPF is a very common issue to everyone. While creating an application, it is quite natural to create an application that has Multilingual Support and which would respond to Current Culture settings in the client computer. In this article, I am going to discuss how to implement a multilingual application.


In the above snapshot you can see a login screen that I have implemented to demonstrate the application.
Try out the sample application from here.

Read Full Article.

Thursday, March 4, 2010

Try Text to Speech for your application

It is really easy and fun to create applications that speaks out for you. With the introduction with System.Speech, it seems to look like even better. It is to be noted, that Windows Environment comes with a unique feature that converts your voice commands to text equivalent long before the introduction to this in .NET. I will discuss now how you can easily use this in your application and get the work done quickly.

Background

Windows Speech Recognization Engine and Narrator utility comes with Windows XP service pack 2 or Office applications. Windows Narrator uses various windows items and speaks instantly. If you have never tried with it, it is time to try it first.

Open Start - > Programs -> Accessories - >Accessibility -> Narrator


After opening you will hear that a person is speaking out some weird terms. Actually this is nothing but your narrator speaking to help you. Actually the checkboxes determines various options like, reading events, Read typed characters etc. You can even change the narrator just by clicking on the Voice Button.
Here you can see Microsoft Sam is listed. This is the default .NET narrator. You can adjust speed, volume, pitch etc of the listed Narrators. You can also add some external Narrators for you if you wish. Now I am going to show you how you can invoke Narrator to be used in your own application.

Old Way
If you are not using .NET Framework 3.0 or above, this must be your only way to do this. First in this case you need to install Speech SDK 5.1. The speech SDK gives you the interface to work with SPVoice commands. The Speech SDK provides you two interfaces. One is for Text to Speech Conversion, while the other is for Speech Recognisation. In this article I am going to discuss only Text  to Speech Conversion.

To do this, first create the Interop to the COM dll that comes with SAPI named speechlib.dll. You need to right click on your project, add Reference and add "Microsoft Speech Object Library" from COM tab.
After you add Interop.Speechlib.dll in your application you need to use some simple lines of code as below to run your application :

using SpeechLib;
SpVoice speech = new SpVoice();
speech.Speak("Hello World",SpeechVoiceSpeakFlags.SVSFlagsAsync);
speech.WaitUntilDone(Timeout.Infinite);

Thus if you run the above application, you will find that Microsoft Sam will say you "Hello World".

NEW Way

With the Introduction of .NET Framework 3.0, Microsoft released Managed API to handle these through your program and it doesnt need anything to be installed. Let us look how we can invoke using the new way.

First Add Reference to System.Speech.dll. You will find that in GAC if you have installed .NET 3.5 to your system.
As shown in the figure, after you add the dll you need to use some simple methods to invoke Speech To Text for your application. 

To invoke this, you need to know about a class called SpeechSynthesizer. This is the main class to handle speech requests from the application and invokes the Narrator utility itself with configured narrator. 
You can configure voice, speech, pitch of the narrator, and change the Narrator voice itself using the object of SpeechSynthesizer class.

Let us see how the code look like :
using System.Speech.Synthesis;

SpeechSynthesizer spsynthesizer = new SpeechSynthesizer();
List<voiceinfo> lstVoice = this.LoadSelectVoiceMenu();
Now when you want to invoke the Speaking utility just call :
spsynthesizer.SelectVoice(lstVoice[0].Name); //Invoke the one which you want
spsynthesizer.Volume = 50; // Can be 1 - 100
spsynthesizer.Rate = 3; // can be 1 - 10 
spsynthesizer.SpeakAsync("Hello World");

The SelectVoice method is used to choose the appropriate Narrator. If you have more than one narrator, you can use this method to SelectVoice. I have used lstVoice[0] which should point to Microsoft Sam. The volume determines the volume of the voice, and Rate determines how fast the narrator speaks.

To Speak out the text, you have two method. I am using SpeakAsync, to call it asynchronously. You can also use Speak itself, which will wait until the text is spoken. While the text is been spoken using SpeakAsync, you can all SpeakAsyncCancel or SpeakAsyncCancelAll anytime to end the narrator instantly.

spsynthesizer.SpeakAsyncCancel(new Prompt("Lets End"));

if invoked will end the SpeakAsync and prompt Lets End.

Conclusion

Thus invoking a Text to Speech for your application become easiest like never before. You can use this without any heck.

In my next entry, I will be discussing about Speech Recognisation. So stay tune.

Monday, January 11, 2010

How to : Expose events from UserControl

In ASP.NET, web user control is used very often to implement modular coding. We replace the repeating blocks of code into an User Control which we add in our web page when required. Technically speaking, ASP.NET web user control is just a subset of a Web Form. You have designer where you can declare controls that comprise the user control, you can even manipulate the code from the code-behind class. The only think that you need is to handle appropriate events within the User Control and add that in the aspx page.

The problem


Generally we place all the controls that comprises the user control private, so that we disallow the pages to access the controls within the user control directly. Thus, we cannot access any events that is associated with any child control within the user control. We have to rely only on the OnLoad event of an user control which most of the time could not be used properly.
To help in such a situation we need to create our custom events and expose them from the user control so that we can handle them easily to the page and do appropriate tasks.
In this article I am going to discuss how to do this :
To make the example most simple, I have create a country/state selection box as an user control. The Usercontrol contains 2 DropdownList items which are placed one after another. There are a few behaviours of the dropdownlist controls. The second dropdown is actually populated from the data of the first one.

Thus when I choose Canada from the first dropdown, I can choose the other states from the second. To do this, I need to handle the SelectedIndexChanged event and populated the second dropdown. Just see the code below (I used XML data for better understanding):
protected void drpCountry_selectedIndexChanged(object sender, EventArgs e)
{
string selecteditem = drpCountry.SelectedValue;
PopulateDropStates(selecteditem);
}


The PopulateDropStates clears all the items in the 2nd dropdown and recreates the items.
private void PopulateDropStates(string p)
{
this.drpState.Items.Clear();
XElement container = doc.Descendants("country").FirstOrDefault(
item => item.Attribute("code").Value.Equals(p));
var elements = container.Descendants();
foreach (XElement elem in elements)
{
ListItem item = new ListItem(elem.Attribute("name").Value
, elem.Attribute("code").Value);
this.drpState.Items.Add(item);
}
if (this.drpState.Items.Count > 0)
this.drpState.Items[0].Selected = true;

}
I have made the dropdownlist private and which lets me to access only the part of the control that I want to expose. Now let say I want to do something when my 2nd dropdown is changed. Aah, I cant do that because as the control is not public, I cant handle the events. So I need to formulate a proxy event from the control and generate that event whenever the selectedindex of the second DropDownlist is changed.

Declaring an Event

Event is an object which raises itself whenever some other behavioral change of the class is made. When an event is raised, we need to pass the actual delegate that it calls. So to work with event, we need to create a delegate which will define the signature of the event handler and the event itself.
public delegate void DropDownSelectionDelegate(
object sender, SelectionChangedEventArgs e);
protected event DropDownSelectionDelegate _drp1selectionChanged;
public event DropDownSelectionDelegate DropDownCountrySelectionChanged
{
add
{
if(this._drp1SelectionChanged == null)
this._drp1selectionChanged += value;
}
remove
{
if(this._drp1SelectionChanged != null)
this._drp1selectionChanged -= value;
}
}
public virtual void OnDropDownCountrySelectionChanged()
{
SelectionChangedEventArgs evt = new SelectionChangedEventArgs(this.drpCountry);
if (this._drp1selectionChanged != null)
this._drp1selectionChanged(this, evt);
}

We have created an instance of a delegate DropDownSelectionDelegate which is the signature of the event _drp1selectionChanged. Thus if you want to handle the event, I need to declare an event handler same to the signature of the delegate.
The event accessor is the public property which exposes the event to the outside. I have added both add/remove to ensure the event can be added and removed using this and also to ensure only one instance of the event is registered. The virtual method OnDropDownCountrySelectionChanged actually raises the event. Thus whenever the event requires invocation in the class, just use this.OnDropDownCountrySelectionChanged() and the event will be raised.

In order to handle the event inthe page, just register the event in the page_load like this :
this.objCountrySelect.DropDownCountrySelectionChanged += new
DropDownSelectionDelegate(methodname);


Or you can directly add the event to control itself:
<uc1:CountryStateSelectBox runat="server"
   ID="ctrySelectbox"
   OnDropDownCountrySelectionChanged="ctrySelectBox_DropDownCountrySelectionChanged">
</uc1:CountryStateSelectBox>


Thus the event handler ctrySelectBox_DropDownCountrySelectionChanged will get raised automatically whenever the country selection is changed.

In this example I have used a custom class SelectionChangedEventArgs which is basically used to send data.
public class SelectionChangedEventArgs : EventArgs
{
private DropDownList _list;
public SelectionChangedEventArgs(DropDownList list)
:base()
{
this._list = list;
}
public DropDownList DropDown
{
get
{
return this._list;
}

}

}

Thus the class is created just to pass the list object with the event argument.

Conclusion


Thus through events you can easily raise your custom events from the control and pass data. Events comes very handy when you want callbacks for long running applications. You can define an event which you raise after an interval.

Thanks for reading my blog.

Author's new book

Abhishek authored one of the best selling book of .NET. It covers ASP.NET, WPF, Windows 8, Threading, Memory Management, Internals, Visual Studio, HTML5, JQuery and many more...
Grab it now !!!