Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Sunday, April 10, 2011

How to Translate and Play/Speak using Microsoft Soap APIs

Some options that are provided by Microsoft to do translation in your application are
  • AJAX Interface
  • SOAP Interface
  • HTTP Interface
In this post I am going to explain translation using SOAP related APIs. You can download a ready to run code, which I have used in this post, from here. Note that in order to run the sample code you will have to provide your AppID(discussed below) in AppID variable.

As I mentioned above, first must thing you have to do in order to do translation in your application is get your AppID from Microsoft. Only after getting this AppID you will be able to use translation APIs. This ID is free of charge and you can get it from here. Do read terms and conditions about using free AppID.

In your .Net 3.5 or above application first of all add a service reference of Microsoft's Web Service that provides the translation related services. Web Service address is http://api.microsofttranslator.com/V2/Soap.svc.  I have given it name 'TranslationService' in my code.

   1:  TranslationService.LanguageServiceClient client = new TranslationService.LanguageServiceClient ();
   2:  //translating from "en" english to "de" german.
   3:  string germanString = client.Translate(AppID, "Hello, how are you", "en", "de", "text/plain", "general");
   4:  //translating back from "german" to "english"
   5:  string englishString = client.Translate(AppID, germanString, "de", "en", "text/plain", "general");
In code snippet above, I am first of all creating an instance of LanguageServiceClient. After that I am translating a "Hello, How are you" from English to German and then I am translating result back in to English. AppID in above code is the free AppID I got from Microsoft. Notice that I am passing "text/plain" in content type parameter which tells the translation service that it is a simple plain text. You can also translate HTML pages by passing "text/html" in content type.

Microsoft's translation service's also provide speaking related features. For example if you want to listen/play a string in English language you can do something like this.

   1:  //this method call will return me url of media file that speaks/plays "Hello, How are you"
   2:  string speakEnglishURL = client.Speak(AppID, "Hello, How are you", "en", "audio/wav");
In code snippet above, I am specifying that provide string "Hello, How are you" is in "en" or English. You can use the returned URL to play or listen to the actual sound.

Microsoft has provided a very simple API for programmers and developers for translation and speaking related services. Now its job of developers to come up with creative ideas which can make maximum use of these APIs and change the world :). In my opinion Windows Phone 7 developers can build very powerful apps using these APIs. You can download complete ready to run code from here. Don't forget to get AppID can put it in 'AppID' variable in sample code, otherwise it won't run.

Saturday, April 9, 2011

When not to use Count in C#

During my daily development I have to deal with IEnumerables quite often. Old habits takes time to go but now I try to use LINQ to Objects as much as possible in my code while dealing with IEnumerables. LINQ to Objects or LINQ in general is one of the best thing that have been added in C# in past couple of years in my personal opinion.

As I said, old habits take time to go, one habit which I am trying to get rid of these days is to avoid using Count property. At countless places in my code I have used this piece of code and I am sure many of you would have done same

   1:  if(SomeCollection.Count == 0)
   2:      DoSomething();
   3:  else
   4:      DoSomethingElse();
In above piece of code you just want to know whether the collection contains any item or not and based on that you will perform some operation. Problem is that to find this yes or no you are traversing the whole list when you use Count. Let's say your collection contain 1000 element. You are traversing whole list just to find out whether there is any item in the list or not. Which doesn't make any sense at all. Instead what we can use is a simple LINQ method 'Any'.

   1:  if(SomeCollection.Any())
   2:      DoSomething();
   3:  else
   4:      DoSomethingElse();
Use of 'Any' will make your code much faster because instead of traversing whole collection 'Any' will return as soon as it finds that there is an element in your collection or even in case there isn't any at all. This is just one example I am sure there will be many more examples in my daily development which can be simplified using LINQ to Objects.

Note that "if you are starting with something that has a .Length or .Count (such as ICollection<T>, IList<T>, List<T>, etc) - then this will be the fastest option, since it doesn't need to go through the GetEnumerator()/MoveNext()/Dispose() sequence required by Any() to check for a non-empty IEnumerable<T> sequence. For just IEnumerable<T>, then Any() will generally be quicker, as it only has to look at one iteration. However, note that the LINQ-to-Objects implementation of Count() does check for ICollection<T> (using .Count as an optimisation) - so if your underlying data-source is directly a list/collection, there won't be a huge difference. In general with IEnumerable<T> : stick with Any()." Taken this paragraph from here

Sunday, February 13, 2011

ScrollViewer causing Slow Performance in WPF

In this post I am going to talk about the performance hit you might get in your WPF application if you are using ScrollViewer. ScrollViewer is used in WPF to display content in a smaller area as compared to content's actual size. In other words, if your content is large and you want to display it in a smaller area, you can put your content inside a ScrollViewer. ScrollViewer will then use scroll bars to display your complete content in smaller area.

If you are planning to use ScrollViewer or you are already using it in your application you might face some performance hit. This performance hit will only be visible if the content you are placing inside ScrollViewer is too large. You can download a ready to run application from here to see the performance hit with and without ScrollViewer. In my case, I am using ScrollViewer around a DataGrid whose ItemsSource is a DataTable. My DataTable contains 1000 rows. 1000 rows are more than enough to make sure that the content is large and it can't be displayed completely without scroll bars.
In my sample application's main view I have a Grid which contain two rows. First row has a Button while second row has a DataGrid enclosed inside a ScrollViewer.

   1:  <Grid>
   2:       <Grid.RowDefinitions>
   3:            <RowDefinition Height="30"/>
   4:            <RowDefinition/>
   5:       </Grid.RowDefinitions>
   6:       <Button Grid.Row="0" Click="Button_Click">Populate Grid</Button>
   7:       <ScrollViewer Grid.Row="1">
   8:            <DataGrid Grid.Row="1" Name="dataGrid" HorizontalAlignment="Stretch"  VerticalAlignment="Stretch"/>
   9:       </ScrollViewer>
  10:  </Grid>
As you can see in XAML above, I am handling click event of button. In this event I am creating a DataTable with 1000 rows and setting this DataTable as ItemsSource of my DataGrid.
If you run the application I specified earlier, you will see a "Populate Grid" button on top. Click this button to populate the DataGrid. By default, as you can see in XAML, DataGrid is inside ScrollViewer. When you will click "PopulateGrid" button, WPF will take around 5 seconds(at least on my system) to display the content of DataGrid. Now let's do a slight change in XAML and get rid of ScrollViewer.

   1:  <Grid>
   2:       <Grid.RowDefinitions>
   3:            <RowDefinition Height="30"/>
   4:            <RowDefinition/>
   5:       </Grid.RowDefinitions>
   6:       <Button Grid.Row="0" Click="Button_Click">Populate Grid</Button>
   7:       <!--<ScrollViewer Grid.Row="1">-->
   8:            <DataGrid Grid.Row="1" Name="dataGrid" MinRowHeight="25" AlternatingRowBackground="LightGray" MinColumnWidth="100" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ColumnHeaderHeight="35"/>
   9:       <!--</ScrollViewer>-->
  10:  </Grid>
As you can see I just have commented out the ScrollViewer. Now DataGrid is directly inside second row of Grid. After making these changes run the application again and click the populate button. This time WPF will display content of DataGrid without any delay or taking anytime.

So what could be the reason behind this performance hit? I think when we are placing the DataGrid inside ScrollViewer, all default UI Virtualizations of DataGrid are getting void as it is now inside ScrollViewer and as a result UI is taking so much time to load the contents of DataGrid.
You can download the ready to run application from here and play with both scenarios.

Monday, February 7, 2011

Faster Controls with UI Virtualization in WPF

A very useful feature in WPF for making faster and interactive UIs is UI virtualization. Let's say, in your WPF application, you have a ComboBox with 10,000 elements in it. When you will click the ComboBox to expand it, it will take quite some time before actually the ComboBox's available options will be displayed in a drop down for selection. The reason is simple, loading 10,000 UI elements in WPF's visual tree naturally takes some time. One thing to keep in mind is that whether your combo box contains 10K element or 100K elements, user will be looking at a very limited number of options at one instance of time. For example if you expand a combo box, at one time you will only be looking at approximately 25 elements. Even if at one time we see only limited amount of items, WPF loads all the item in visual tree when you click expand button and it takes memory and time. By enabling UI virtualization in your ComboBox, WPF will create only those elements in memory which you can see at one time. This will make combo box expand in no time and as a result even if your combo box contains 10K elements, WPF will take no time to expand it. As you will move the scroll bar down to see more items in ComboBox, WPF will dynamically dispose the elements which will go out of the view as a result of scrolling and will create & load new items in ComboBox accordingly. 
Some controls uses UI Virtualization by default like ListBox and ListView but some controls don't for example ComboBox. You can use following XAML to enable UI virtualization in a combo box and similarly in any control you want.

   1:  <ComboBox ItemsSource="{Binding Path=Collection}">
   2:       <!--comment ComboBox.ItemsPanel below to see how much time WPF takes to load this ComboBox without UI virtualization-->
   3:       <ComboBox.ItemsPanel>
   4:            <ItemsPanelTemplate>
   5:                 <VirtualizingStackPanel />
   6:            </ItemsPanelTemplate>
   7:        </ComboBox.ItemsPanel>
   8:  </ComboBox>
I have uploaded an application which you can use to see the difference in loading time with and without UI virtualization. You can download this application from here. Comment the ComboBox.ItemPanel in XAML to note the time it takes without UI Virtualization and uncomment ComboBoc.ItemPanel to note time it takes with UI Virtualization.

Sunday, January 30, 2011

DataGrid Validation using IDataErrorInfo in MVVM - WPF

In this post I will demo how you can apply validation rules on WPF's DataGrid using IDataErrorInfo interface. This example uses popular MVVM pattern but if you are not using MVVM you can still grasp the main idea about using IDataErrorInfo for validation in WPF. I will create a DataGrid in my application which will have two columns Name and Age. I will apply two validation rules on my DataGrid. 1) Name cannot be empty. 2) Age must be greater than 20. I will notify user about the validation error using tooltip displaying corresponding error and a red border around the cell which contains invalid value. You can download complete ready to run demo from here.

I have defined a class Person which consist of two fields Name and Age. I will bind item source of my DataGrid with collection of Person class to display list of persons in my DataGrid.

   1:      /// <summary>
   2:      /// Derived from Base, Implements IDataErrorInfo
   3:      /// </summary>
   4:      public class Person : Base, IDataErrorInfo
   5:      {
   6:          string m_Name;
   7:          int m_Age;
   8:   
   9:          public Person()
  10:          {
  11:              m_Name = string.Empty;
  12:              m_Age = 0;
  13:          }
  14:   
  15:          public string Name
  16:          {
  17:              get
  18:              {
  19:                  return m_Name;
  20:              }
  21:              
  22:              set
  23:              {
  24:                  if(value != m_Name)
  25:                  {
  26:                      m_Name = value;
  27:                      //notify the binding that my value has been changed
  28:                      OnPropertyChanged("Name");
  29:                  }
  30:              }
  31:          }
  32:   
  33:          public int Age
  34:          {
  35:              get
  36:              {
  37:                  return m_Age;
  38:              }
  39:   
  40:              set
  41:              {
  42:                  if (value != m_Age)
  43:                  {
  44:                      m_Age = value;
  45:                      //notify the binding that my value has been changed
  46:                      OnPropertyChanged("Age");
  47:                  }
  48:              }
  49:          }
  50:   
  51:          public string Error
  52:          {
  53:              get { throw new NotImplementedException(); }
  54:          }
  55:   
  56:          //IDataErrorInfo Property
  57:          public string this[string columnName]
  58:          {
  59:              get 
  60:              { 
  61:                  //this get will be invoked everytime user change the Name or Age filed in Datagird
  62:                  //columnName contains the property name which is modified by user.
  63:                  string error = string.Empty;
  64:                  switch(columnName)
  65:                  {
  66:                      case "Name":
  67:                          //if user changes the name field, I check if the new value is empty or not
  68:                          //if it is empty I set the error message accordingly.
  69:                          if(string.IsNullOrEmpty(m_Name))
  70:                              error = "Name cannot be empty";
  71:                      break;
  72:   
  73:                      case "Age":
  74:                          //if user change the Age, I verify that Age is greater than 20,
  75:                          //if not I set the error message.
  76:                          if(m_Age < 20)
  77:                              error = "Age must be greater than 20";
  78:                      break;
  79:                  }
  80:                  //just return the error or empty string if there is no error
  81:                  return error;
  82:              }
  83:           
  84:          }
  85:      }
Note that Person class has been derived from Base which is implementing INotifyPropertyChanged interface to tell the binding instantly that a proprty.

I am using the Person class created above in MainWindowData which is the main class whose object is set as DataContext of MainWindow i.e. our view. This is done in MainWindow.xaml.cs. MainWindowData has a PersonCollection which is an ObservableCollection of  Person class and this collection will be set as an item source of DataGrid.

I have defined application's view/UI in XAML. It consists of a style for TextBlock and a DataGrid consisting of two template columns, first for Name second for Age. Inside window's resources, I have defined a style for TextBlock type. In this style I am defining that whenever Validation Error occurs, display the error message in a tooltip. I will be using this style in my CellTemplate for both the columns of my DataGrid.

   1:  <Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}">
   2:       <Style.Triggers>
   3:            <Trigger Property="Validation.HasError" Value="true">
   4:                 <Setter Property="ToolTip"
   5:                 Value="{Binding RelativeSource={RelativeSource Self},
   6:                 Path=(Validation.Errors)[0].ErrorContent}"/>
   7:            </Trigger>
   8:       </Style.Triggers>
   9:  </Style>
I have binded ItemSource of my DataGrid with PersonCollection. DataGrid consists of two template columns Name and Age. I have set TextBlock as CellTemplate and TextBox as CellEditingTemplate for both the columns. I have applied the style on CellTemplate which is defined in window resources to display the error in tooltip.

   1:  <DataGrid ItemsSource="{Binding PersonCollection}" AlternatingRowBackground="Wheat" AutoGenerateColumns="False">
   2:              <DataGrid.Columns>
   3:                  <DataGridTemplateColumn  Header="Name" MinWidth="150">
   4:                      <DataGridTemplateColumn.CellTemplate>
   5:                          <DataTemplate>
   6:                              <TextBlock Style="{StaticResource ResourceKey=TextBlockStyle}" Text="{Binding Path=Name,  UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"/>
   7:                          </DataTemplate>
   8:                      </DataGridTemplateColumn.CellTemplate>
   9:   
  10:                      <DataGridTemplateColumn.CellEditingTemplate>
  11:                          <DataTemplate>
  12:                              <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
  13:                          </DataTemplate>
  14:                      </DataGridTemplateColumn.CellEditingTemplate>
  15:                  </DataGridTemplateColumn>
  16:   
  17:                  <DataGridTemplateColumn Header="Age" MinWidth="150">
  18:                      <DataGridTemplateColumn.CellTemplate>
  19:                          <DataTemplate>
  20:                              <TextBlock Style="{StaticResource ResourceKey=TextBlockStyle}" Text="{Binding Age, UpdateSourceTrigger=PropertyChanged, NotifyOnValidationError=True, ValidatesOnDataErrors=True}"/>
  21:                          </DataTemplate>
  22:                 </DataGridTemplateColumn.CellTemplate>
  23:   
  24:                 <DataGridTemplateColumn.CellEditingTemplate>
  25:                      <DataTemplate>
  26:                           <TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}"/>
  27:                      </DataTemplate>
  28:                 </DataGridTemplateColumn.CellEditingTemplate>
  29:            </DataGridTemplateColumn>
  30:       </DataGrid.Columns>  
  31:  </DataGrid>
These were the main parts of complete example. If user enters an empty string in the Name column, he/she will get error like this

You can download the complete ready to run sample from here and play with it.



Sunday, January 23, 2011

Create DataGrid in WPF using code

In this post I will explain a way to create DataGrid in WPF through code. I will use a DataTable with two columns as a DataSource for the DataGrid. I will display one column as TextBox while the second column will be displayed as ComboBox. You can download complete sample from here. My main Window contains single Grid inside which I will display my DataGrid. I will use MainGrid_Initialized event to create DataGrid.


 Inside MainGrid_Initialized event I am creating a DataGrid and adding two columns inside it. One for the TextBox and other for the ComboBox. Then I am setting a DataTable as DataSource for my DataGrid which contains two columns "TextBoxColumn" and "ComboBoxColumn". At the end, I am placing my DataGrid in the Main Window's Grid.
   1:  DataGrid dataGrid = new DataGrid();
   2:  dataGrid.AutoGenerateColumns = false;
   3:   
   4:  dataGrid.Columns.Add(CreateTextBoxColumn());
   5:  dataGrid.Columns.Add(CreateComboBoxColumn());
   6:  //set DataTable as item source of dataGrid
   7:  dataGrid.ItemsSource = GetDataTable().AsDataView();
   8:   
   9:  //place DataGrid inside main Grid
  10:  Grid.SetColumn(dataGrid,0);
  11:  Grid.SetRow(dataGrid,0);
  12:  MainGrid.Children.Add(dataGrid);
In CreateTextBoxColumn method I am defining my TextBox based column. I am creating two templates one for viewing(TextBlock) and other for editing (TextBox). I am also creating bindings between DataTable's "TextBoxColumn" with the TextBlock and the TextBox templates.

   1:  private DataGridTemplateColumn CreateTextBoxColumn()
   2:          {
   3:              //create a template column
   4:              DataGridTemplateColumn templateColumn = new DataGridTemplateColumn();
   5:              //set title of column
   6:              templateColumn.Header = "TextBoxColumn";
   7:              //non editing cell template.. will be used for viweing data
   8:              DataTemplate textBlockTemplate = new DataTemplate();
   9:              FrameworkElementFactory textBlockElement = new FrameworkElementFactory(typeof(TextBlock));
  10:              Binding textBlockBinding = new Binding("TextBoxColumn");
  11:              textBlockElement.SetBinding(TextBlock.TextProperty, textBlockBinding);
  12:              textBlockTemplate.VisualTree = textBlockElement;
  13:              templateColumn.CellTemplate = textBlockTemplate;
  14:   
  15:              //editing cell template ... will be used when user will edit the data
  16:              DataTemplate textBoxTemplate = new DataTemplate();
  17:              FrameworkElementFactory textboxElement = new FrameworkElementFactory(typeof(TextBox));
  18:              Binding textboxBinding = new Binding("TextBoxColumn");
  19:              textboxElement.SetBinding(TextBox.TextProperty, textboxBinding);
  20:              textBoxTemplate.VisualTree = textboxElement;
  21:              templateColumn.CellEditingTemplate = textBoxTemplate;
  22:              return templateColumn;
  23:          }
Similarly, I am creating a column for ComboBox

   1:   private DataGridTemplateColumn CreateComboBoxColumn()
   2:          {
   3:              //create a template column
   4:              DataGridTemplateColumn templateColumn = new DataGridTemplateColumn();
   5:              //set title of column
   6:              templateColumn.Header = "ComboBoxColumn";
   7:              //non editing cell template.. will be used for viweing data
   8:              DataTemplate textBlockTemplate = new DataTemplate();
   9:              FrameworkElementFactory textBlockElement = new FrameworkElementFactory(typeof(TextBlock));
  10:              Binding textBlockBinding = new Binding("ComboBoxColumn");
  11:              textBlockElement.SetBinding(TextBlock.TextProperty, textBlockBinding);
  12:              textBlockTemplate.VisualTree = textBlockElement;
  13:              templateColumn.CellTemplate = textBlockTemplate;
  14:   
  15:              //editing cell template ... will be used when user will edit the data
  16:              DataTemplate comboboxTemplate = new DataTemplate();
  17:              FrameworkElementFactory comboboxElement = new FrameworkElementFactory(typeof(ComboBox));
  18:              Binding comboboxBinding = new Binding("ComboBoxColumn");
  19:              comboboxElement.SetBinding(ComboBox.TextProperty, comboboxBinding);
  20:   
  21:              //combo box will show these options to select from
  22:              comboboxElement.SetValue(ComboBox.ItemsSourceProperty, new List<string> { "Value1", "Value2" ,"Value3", "Value4" });
  23:              comboboxTemplate.VisualTree = comboboxElement;
  24:              templateColumn.CellEditingTemplate = comboboxTemplate;
  25:              return templateColumn;
  26:          }
You can download complete sample from here and play with it

Saturday, January 22, 2011

ComboBox in WPF’s DataGrid through XAML

One thing I did recently was to allow user select value of a cell in WPF’s DataGrid from a ComboBox. I was using MVVM and the DataGrid was in my view so I had to define the columns and their bindings through XAML. After reading some articles on internet and some experimentation I was able to achieve the goal and I am sharing my solution here.

   1:  <DataGrid ItemsSource=”{Binding Path=CustomObjectCollection}” 
   2:   AutoGenerateColumns=”False>
   3:   <DataGrid.Columns>
   4:    <DataGridTemplateColumn>
   5:     <DataGridTemplateColumn.CellTemplate>
   6:      <DataTemplate>
   7:       <TextBlock Text=”{Binding Path=CustomObjectStringMember}”/>
   8:      </DataTemplate>
   9:     </DataGridTemplateColumn.CellTemplate>
  10:     <DataGridTemplateColumn.CellEditingTemplate >
  11:      <DataTemplate>
  12:       <ComboBox ItemsSource=”{Binding Path=CustomObjectListMember}” 
  13:       Text=”{Binding Path=CustomObjectStringMember}”/>
  14:      </DataTemplate>
  15:     </DataGridTemplateColumn.CellEditingTemplate>
  16:    </DataGridTemplateColumn>
  17:   </DataGrid.Columns>
  18:  </DataGrid>
In the code snippet above, CustomObjectCollection is an ObservableCollection where CustomObject is custom class I have written. Each instance of CustomObject in my ObservableCollection represents one row in my DataGrid. My CustomObject has two members ‘CustomObjectStringMember’ which is a String and ‘CustomObjectListMember’ which is List. The ComboBox in DataGrid will display the items in ‘CustomObjectListMember’ as possible options for selection and the selected value will be stored in ‘CustomObjectStringMember’ variable of my ‘CustomObject’ instance.

I have defined two templates inside XAML of my column. First one i.e. DataGridTemplateColumn.CellTemplate displays the selected value as TextBlock when the user is only viewing the the data in DataGrid. Second i.e. DataGridTemplateColumn.CellEditingTemplate will be activated when user will click on particular cell to edit its value. This template will update the cell from TextBlock to ComboBox and will allow user to select any value from the ComboBox. As soon as the cell will lose focus the CellTemplate will again replace the CellEditingTemplate