Mathias Brandewinder on .NET, F#, VSTO and Excel development, and quantitative analysis / machine learning.
by Mathias 27. September 2010 18:15

An interesting user interface issue came up in the project I am working on right now.  In a nutshell, the user needs to select an item from a list of existing items. This sounds straightforward, except that the list of items has hundreds of elements. Clearly, a combo box or a list box won’t do the job – we need a convenient way to reduce the choices and help the user find what he needs.

One suggestion I liked was to use something similar to an auto-complete: type in a few letters, and show only “relevant” items to chose from:

auto-complete-me

While digging into the question, I came into a .NET interface I didn’t know, ICollectionView. Essentially, it is a collection that is suitable for WPF databinding, and also has filtering capabilities. It stores a source collection, which contains all the items, but when a filter is applied to it, WPF will only “see” the filtered results. 

Displaying a standard list

Let’s first create a WPF application, and warm up by adding a simple class, Product:

public class Product
{
   public string Name
   {
      get;
      set;
   }
}

Now let’s add a WPF UserControl, SearchAndSelectView.xaml. The control has a TextBlock, where we will display the name of the selected Product, a TextBox, where the user will type in the filtering text, and a ListBox, where we will display a selection of Products.

<UserControl x:Class="QuickSearchAndSelect.SearchAndSelectView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d">
   <StackPanel Width="150">
      <TextBlock Text="{Binding Path=SelectedProduct.Name}"/>
      <TextBox x:Name="Filter"/>
      <ListBox Height="150" x:Name="Products"
               ItemsSource="{Binding Path=Products}"
               SelectedItem="{Binding Path=SelectedProduct}">
         <ListBox.ItemTemplate>
            <DataTemplate>
               <StackPanel>
                  <TextBlock Text="{Binding Path=Name}"/>
               </StackPanel>
            </DataTemplate>
         </ListBox.ItemTemplate>
      </ListBox>
   </StackPanel>
</UserControl>

More...

by Mathias 26. September 2010 08:12

The most awesome free developer event on the west coast is back again, and it looks like it will be even more awesome this year. The 5th edition of Silicon Valley Code Camp is taking place Saturday and Sunday Oct 9th and 10th, 2010, at Foothill College, in Los Altos Hill. There are 194 sessions, already over 1,600 registrations, with topics for all tastes - .NET, Java, Cloud Computing, Python, Javascript, mobile development, and more.

The 2010 schedule is up here. I will be giving 2 talks, on Test-Driven Development, and on Mocking. Both are on Sunday – hope to see you there!

by Mathias 19. September 2010 16:48

fail-owned-translation-failI have been involved recently with a project for a foreign company with offices in the US; the US team receives lots of documents in a foreign language which require translation, and they were interested in a way to speed up the process, using Bing Translator and Google Translate.

Why not just pick one? Both are awesome, but if you have tried them, you know the results can be somewhat random. Having the option to compare their respective results is a good way to make sure you end up with something which makes sense.

This sounded like a perfect case for the Strategy Pattern. I started by defining a common interface:

public interface ITranslator
{
  string TranslateToHindi(string original);
  string TranslateToEnglish(string original);
}

… and implemented two versions, the BingTranslator and the GoogleTranslator, using the API for each of these services. So far so good, but when I started working on the user interface, I ran into a small problem. My user interface has just 2 buttons, “translate to English”, and “Translate to Hindi”, and Ideally, I would have liked to  just pass the specific language pair to use, along these lines:

private void toEnglishButton_Click(object sender, RibbonControlEventArgs e)
{
  ITranslator translator = this.GetTranslator();
  this.TranslateStuff(translator, stuffToTranslate, “en”, “hi”);
}

More...

by Mathias 7. September 2010 16:56

In my previous posts, I explored how to identify text in a PowerPoint slide and use the Google .NET API to translate it; let’s put it all together in a simple VSTO add-in for PowerPoint 2007.

The translation functionality is displayed in a Custom Task Pane, where you can pick the language of origin, and the language to translate to. I used the same general design I presented in my Excel add-in tutorial, using WPF controls in the task pane with the MVVM pattern, leveraging the small yet very useful MVVM foundation framework. When running, this is how the add-in looks like:

TranslatorStart

TranslatorEnd

I added only 3 languages in there, but it is fairly easy to modify the code and get it to work with any language pair supported by Google translate.

Download code sample

by Mathias 2. September 2010 17:04

The beauty of working with a framework like .NET is that when you have a problem, chances are, someone else did before you, and might have even resolved it for you. In our last post, I explained how to find text in a PowerPoint slide using C#. My goal was to translate it using the Google Translate service, and I intended to write my own code to call the web service and retrieve the translation. Turns out, there is a .NET API for Google Translate, ready to use, which does it for you already (of course, I found that out already after rolling out my own code, which wasn’t nearly as good).

Building up where we left off, I quickly wrote this class, which will translate the slide currently in view; I think the code is self-explanatory: get the slide, create a Google translator, pass it the language of origin and of destination, and translate every chunk of text you find! The only thing I needed to do was to download GoogleTranslateAPI_0.3.1, add the dll to the project as a reference.

namespace ClearLines.PowerPointTranslator
{
   using Google.API.Translate;
   using PowerPoint = Microsoft.Office.Interop.PowerPoint;

   public class SlideTranslator
   {
      public static void TranslateSlide(Language from, Language to)
      {
         var googleTranslator = new TranslateClient("http://www.clear-lines.com");

         var powerpoint = Globals.ThisAddIn.Application;
         var slide = (PowerPoint.Slide)powerpoint.ActiveWindow.View.Slide;

         foreach (PowerPoint.Shape shape in slide.Shapes)
         {
            if (shape.HasTextFrame == Microsoft.Office.Core.MsoTriState.msoTrue)
            {
               var textFrame = shape.TextFrame;
               var textRange = textFrame.TextRange;
               TranslateTextRange(textRange, googleTranslator, from, to);
            }
         }
      }

      public static void TranslateTextRange(
         PowerPoint.TextRange textRange, 
         TranslateClient translator, 
         Language from,
         Language to)
      {
         var paragraphs = textRange.Paragraphs(-1, -1);
         foreach (PowerPoint.TextRange paragraph in paragraphs)
         {
            var text = paragraph.Text;
            text = text.Replace("\r", "");
            paragraph.Text = translator.Translate(text, from, to);
         }
      }
   }
}

Later this week, after I do some code scrubbing, I’ll post the entire VSTO solution. Until then, have fun – it’s almost the week-end!

Comments

Comment RSS