Article Posted: AutoCompleteComboBox for Silverlight

I have posted an article at CodeProject on customization of the Silverlight AutoCompleteBox to be used as a type-ahead ComboBox in LOB applications at CodeProject. The AutoCompleteComboBox can be used in typical Object-to-Object associations (one that we typically encounter when creating associations in Entity Framework) as well as Foreign Key associations (the new association type introduced with Entity Framework 4).

Here’s a sample usage of the control in a typical MVVM scenario:

  • Object to Object Association:

    Example data structure:

    public class SalesOrderDetail
    {
        Product product;
        public Product Product
        {
            get { return product; }
            set { product = value; }
        }
    }
    

    Example control usage:

     <custom:AutoCompleteComboBox
       SelectedItemBinding="{Binding Product, Mode=TwoWay}"
       ItemsSource="{Binding Path=Products, Source={StaticResource ViewModel}}"
     />
    
  • Foreign Key Association:

    Example data structure:

    public class SalesOrderDetail
    {
        int productID;
        public int ProductID
        {
            get { return productID; }
            set { productID = value; }
        }
    }
    

    Example control usage:

     <custom:AutoCompleteComboBox
       SelectedValue="{Binding ProductID, Mode=TwoWay}"
       SelectedValuePath="ProductID"
       ItemsSource="{Binding Path=Products, Source={StaticResource ViewModel}}"
     />
    

To view the implementation details, you can read the full article at :
http://www.codeproject.com/KB/silverlight/AutoComplete_ComboBox.aspx

The source code along with a demo project can be downloaded from the article as well as here (28 KB). Remember to rename the file as zip for extraction.

Avoiding hard-coded strings while raising or handling PropertyChanged event

While developing WPF/Silverlight applications, and more specifically while following the Model-View-ViewModel (MVVM) pattern we will find ourselves implementing INotifyProprertyChanged most of the times. The default implementation of PropertyChanged event takes the property name as string in the PropertyChangedEventArgs which is not much robust. There are several ways to address the issue:

  • Use reflection to verify that the property actually exists, as demonstrated once by Josh Smith.
  • Use Injection using some Aspect Oriented Programming framework, like PostSharp
  • Use Expression Trees as described by Michael Sync and Davy Brion

Personally, I prefer using expression trees. So, instead of writing this:

public string MyProperty
{
    get { return this.myProperty; }
    set { this.myProperty = value; this.RaisePropertyChanged("MyProperty"); }
}

We can write:

public string MyProperty
{
    get { return this.myProperty; }
    set { this.myProperty = value; this.RaisePropertyChanged( MyObj => MyObj.MyProperty ); }
}

The same issue exists looking at the other side. When we subscribe to PropertyChanged event of an object, we get the property name again as a string. One way is to use the GetPropertyName( ExpressionTree ) extension method from the above implementation in our if and case statements. Also, Josh nicely addressed the issue in this post, thus allowing us to write:

MyClass myObject = new MyClass();
PropertyObserver<MyClass> observer = new PropertyObserver<MyClass>(myObject)
    .RegisterHandler(myObj => myObj.MyProperty1, myObj => { /* handle change in MyProperty1 */ })
    .RegisterHandler(myObj => myObj.MyProperty2, MyProperty2HandlerMethod  );

Notice that Josh used IWeakEventListener that isn’t available for Silverlight but luckily Pete O’ Hanlon provided us with a Silverlight version of Josh’s work here.

So, combining the great efforts of all these people, we are going to have a better MVVM experience.

IValueConverters: A great tool in developing WPF/Silverlight applications

IValueConverters in WPF/Silverlight are a very powerful tool in UI presentation, especially, when following the MVVM pattern. In MVVM, where everything in the View is bounded to some property from ViewModel, IValueConverters come handy because often the properties in the ViewModel do not necessarily return the same data type that the View needs. For instance, we can have a boolean IsVisible property in the ViewModel but the UI controls need a Visibility enumeration (with values Visibility.Collapsed and Visibility.Visible) to properly consume it. The great thing about IValueConverters is that they take an object and return an object, so its upto the innovation of developer to make the most out of them.

In this post, I will be demonstrating the powers of IValueConverters by representing a simple boolean variable, that has just two possible values, in several ways. Here’s a screenshot from the application. The bindings in the left column are two way, thus the change in any one of the controls is immediately reflected in the whole view. Have a look:

ivalueconvertersdemo

The ViewModel class exposes only one boolean property to the View. Here’s the code:

public class SampleViewModel : System.ComponentModel.INotifyPropertyChanged
{
    bool boolProperty;

    public bool BoolProperty
    {
        get { return boolProperty; }
        set { boolProperty = value; RaisePropertyChanged("BoolProperty"); }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
    }

}

The View consumes the boolean property using:

  • Default Boolean To String Converter (with Values = True, False)
  • Boolean to String Converter (with values = Yes, No)
  • Boolean to String Converter (with values = Start, Stop)
  • Boolean to Brush Converter (with colors Green, Red)
  • Boolean to Opacity Converter (with opacity 100%, 10%)
  • Boolean to FontStyle Converter (with styles Normal, Italic)
  • Boolean to Visibility Converter

Here’s the code for the View:

<UserControl x:Class="IValueConvertersDemo.View.SampleView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:IValueConvertersDemo.ViewModels"
    xmlns:converter="clr-namespace:IValueConvertersDemo.Converters"
    >
    <UserControl.Resources>
        <vm:SampleViewModel x:Key="ViewModel" BoolProperty="True" />
        <converter:BoolToColorConverter x:Key="BoolToColorConverter" />
        <converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
        <converter:BoolToStringConverter x:Key="BoolToStringConverter" />
        <converter:BoolToDoubleConverter x:Key="BoolToDoubleConverter" />
        <converter:BoolToFontStyleConverter x:Key="BoolToFontStyleConverter" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" DataContext="{StaticResource ViewModel}" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <StackPanel Grid.Column="0" Margin="10" HorizontalAlignment="Left">
            <TextBlock Margin="10" FontSize="18" Text="Two-way" />
            <CheckBox Margin="10" Content="BoolProperty" IsChecked="{Binding BoolProperty, Mode=TwoWay}" />
            <TextBox Margin="10" Width="100" Text="{Binding BoolProperty, Mode=TwoWay}" />
            <TextBox Margin="10" Width="100" Text="{Binding BoolProperty, Mode=TwoWay, Converter={StaticResource BoolToStringConverter}, ConverterParameter='Yes,No'}" />
            <TextBox Margin="10" Width="100" Text="{Binding BoolProperty, Mode=TwoWay, Converter={StaticResource BoolToStringConverter}, ConverterParameter='Start,Stop'}" />
        </StackPanel>

        <StackPanel Grid.Column="1"  Margin="10">
            <TextBlock Margin="10" FontSize="18" Text="One-way" />
            <StackPanel Margin="10" Orientation="Horizontal">
                <Ellipse Height="50" Width="50" Fill="{Binding BoolProperty, Converter={StaticResource BoolToColorConverter}}" HorizontalAlignment="Left" />
                <TextBlock Margin="5" VerticalAlignment="Center" Text="Color(Green/Red) depending on bool property" />
            </StackPanel>
            <StackPanel Margin="10" Orientation="Horizontal">
                <Rectangle Fill="Blue" Height="50" Width="50" Opacity="{Binding BoolProperty, Converter={StaticResource BoolToDoubleConverter}}" HorizontalAlignment="Left" />
                <TextBlock Margin="5" VerticalAlignment="Center" Text="Opacity(100%/10%) depending on bool property" />
            </StackPanel>
            <TextBlock Margin="10" Text="Fontstyle(Normal/Italic) depending on bool property" FontStyle="{Binding BoolProperty, Converter={StaticResource BoolToFontStyleConverter}}" />
            <TextBlock Margin="10" Text="This text is visible only if bool value is true" Visibility="{Binding BoolProperty, Converter={StaticResource BoolToVisibilityConverter}}" />
        </StackPanel>

    </Grid>
</UserControl>

Notice that a boolean variable can only be assigned two values: True and False. Yet, still, we are able to use that in several different ways. Thus IValueConverters provide endless possibilities in WPF data presentation. Its only upto the brain of developer how to exploit them.

The sourcecode for the various converters is included with the sample application that can be downloaded here. Make sure you rename the file to .zip for extraction.

Beginning MVVM: The Basics

WPF and Silverlight experts talk a lot about the new Model-View-ViewModel pattern these days. The powerful databinding support in WPF framework provides the basis for MVVM pattern. In this post, I will be highlighting some points that beginners may need to know to start learning MVVM.

To start with MVVM, you must know the basics of WPF/Silverlight databinding and how to data-bind controls using XAML constructs. The thing to note is that if you data-bind a UI control to an object (using the DataContext dependency property), then all of the public properties of that data-object are available to the child controls. In MVVM, the view (a UI control/page) is data-bound to a ViewModel (a simple C# class). The ViewModel exposes all the data and commands the View needs via properties. The View, then declaratively binds its UI controls to corresponding properties and commands of the ViewModel via XAML constructs.

As concepts are more clarified through examples, I am presenting a very simple example. Lets build a Silverlight MVVM version for this UI:
mvvm-picture1

The Listbox presents a list of persons and the right section presents the details of a selected person. To start with MVVM, we will make a ViewModel class containing two properties: a PersonList property that will be providing list of persons for the Listbox, and a SelectedPerson property that will contain the reference to the selected person. Here’s a crud implementation for the class:

public class PersonViewModel : System.ComponentModel.INotifyPropertyChanged
{
    ObservableCollection<Person> personList;
    Person selectedPerson;

    public PersonViewModel()
    {
        //populate some sample data
        personList = new ObservableCollection<Person>()
        {
            new Person(){Name="Syed Mehroz Alam", Age=10, City="Karachi", Country="Pakistan"},
            new Person(){Name="Zinedine Zidane", Age=20, City="Marseille", Country="France"},
            new Person(){Name="Ronaldinho", Age=30, City="Porto Alegre", Country="Brazil"},
            new Person(){Name="John Smith", Age=40, City="Washington", Country="USA"}
        };
    }

    #region Properties

    public ObservableCollection<Person> PersonList
    {
        get { return personList; }
    }

    public Person SelectedPerson
    {
        get { return selectedPerson; }
        set
        {
            selectedPerson = value;
            RaisePropertyChanged("SelectedPerson");
        }
    }

    #endregion

    #region INotifyPropertyChanged Members

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

Now we have this View-Model ready to be consumed by a View. So in a new UserControl, we will instantiate the ViewModel class through XAML in the resources section and will data-bind the View to it using DataContext property of the main control of the View, in our case, a Grid named LayoutRoot. Since the LayoutRoot is data-bound to the ViewModel class, we can use its public properties as the DataSources of our other controls in the View. For our example, we will assign Listbox’s ItemSource to ViewModel.PersonList property and Listbox’s SelectedItem to ViewModel.SelectedPerson property. The right section will be bound to the SelectedPerson and will contain TextBoxes for displaying details of that person. Here’s the XAML code:

<UserControl x:Class="MVVMExample1.View.PersonView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewmodel="clr-namespace:MVVMExample1.ViewModel"
    >
    <UserControl.Resources>
        <viewmodel:PersonViewModel x:Key="ViewModel" />
    </UserControl.Resources>

    <!-- Databind the root control to the ViewModel class -->
    <!-- This way, all the public properties of ViewModel class become available to us -->
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource ViewModel}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <!-- The listbox gets its ItemSource from ViewModel.PersonList property -->
        <!-- Also, the SelectedItem is bound to ViewModel.SelectedPerson property -->
        <ListBox Grid.Column="0" Margin="5"
                 ItemsSource="{Binding PersonList}"
                 DisplayMemberPath="Name"
                 SelectedItem="{Binding SelectedPerson, Mode=TwoWay}"
                 />

        <!-- Databind the right section to ViewModel.SelectedPerson property -->
        <Grid x:Name="PersonDetails" Grid.Column="1" DataContext="{Binding SelectedPerson}" Margin="5" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="150" />
        </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="30" />
                <RowDefinition Height="20" />
                <RowDefinition Height="20" />
                <RowDefinition Height="20" />
                <RowDefinition Height="20" />
            </Grid.RowDefinitions>
            <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="Person Details" FontSize="15" />

            <TextBlock Grid.Row="1" Grid.Column="0" Text="Name" />
            <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Name, Mode=TwoWay}" />

            <TextBlock Grid.Row="2" Grid.Column="0" Text="Age" />
            <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Age, Mode=TwoWay}" />

            <TextBlock Grid.Row="3" Grid.Column="0" Text="City" />
            <TextBox Grid.Row="3" Grid.Column="1" Text="{Binding City, Mode=TwoWay}" />

            <TextBlock Grid.Row="4" Grid.Column="0" Text="Country" />
            <TextBox Grid.Row="4" Grid.Column="1" Text="{Binding Country, Mode=TwoWay}" />
        </Grid>

    </Grid>
</UserControl>

That’s all, our sample application is ready to be run. Observe how selecting a person updates the person details section. Also observe that the databindings are TwoWay and changing the name of a person in the details section is reflected in the ListBox panel as well.

Note that in Silverlight, we do not have built-in support for commands and triggers like WPF. So in order to execute some code upon a button click, we will either need manual hooking of the button’s Click event, a separate third party extension(e.g. SLExtensions, Prism or SilverlightFX) or make our own implementation. More on this in some later post.

Notice that MVVM seems difficult at first, but as soon as you create your first UI using this pattern, you will find yourself thinking your application in terms of Dependency Properties and IValueConverters. Beware, MVVM is quite addictive. Karl Shifflett presents some great MVVM resources on this page. Be sure to bookmark that page for new MVVM stuff.

The source code for the example UI we discussed can be downloaded here. The file needs to be renamed to .zip for extraction. This is “WordPress File Download Pattern” 🙂