It’s often necessary to modify or format some of the raw data received by your data tier application or other data sources. In Silverlight, you can create your own value converter and introduce your own formatting rules. In this blog post I will create a simple value converter that formats double values, and then use it with a RadComboBox.

First, let’s create a class that will represent our data source. The equivalent of this class in more realistic scenario would be a proxy class generated by your data tier application in case you use RIA services.

    public class Data : List<Item>  
    {  
        public Data()  
        {  
            this.Add(new Item() { Name = "Ferrari", Price = 120000 });  
            this.Add(new Item() { Name = "Mercedes", Price = 100000 });  
            this.Add(new Item() { Name = "BMW", Price = 90000 });  
            this.Add(new Item() { Name = "Ford", Price = 50000 });  
        }  
    } 

 

The Item class can be any class that implements the INotifyPropertyChanged interface. In this case the Item class has only two properties Name and Price.

To data bind the data source class we have just created, you should set the DataContext property of RadComboBox like this:

Data context = new Data();  
radCombo.DataContext = context; 

 

Since we want to bind our RadComboBox to the items that are contained in Data, not the Data class itself, we can either use the DisplayMemberPath, a property of RadComboBox, or create an ItemTemplate. Otherwise, if you just simply set the DataContext to the data source you will end up with a ToString() representation of your Data class.

To have our two properties, Name and Price, appear in a single ComboBoxItem we should create a custom template. Here is a sample implementation of this:

  <telerik:RadComboBox x:Name="radCombo" Height="25" Width="120" ItemsSource="{Binding}">  
            <telerik:RadComboBox.ItemTemplate> 
                <DataTemplate > 
                    <Grid> 
                        <Grid.ColumnDefinitions> 
                            <ColumnDefinition Width="*"/>  
                            <ColumnDefinition Width="*"/>  
                        </Grid.ColumnDefinitions> 
                        <TextBlock Text="{Binding Name}" Grid.Column="0" /> 
                        <TextBlock Margin="15,0,0,0" Grid.Column="1" Text="{Binding Price}" /> 
                    </Grid> 
                </DataTemplate> 
            </telerik:RadComboBox.ItemTemplate> 
        </telerik:RadComboBox> 

 

The result of running this code should be similar to this:

ComboBox without formatting 

Obviously, we cannot distinguish whether the numbers part of the combobox item are prices or telephone numbers. What we would like to achieve is simply format the UI representation of this values without modifying the data source itself. In Silverlight and WPF you can use the IValueConverter interface to introduce your own format logic. The interface has two virtual methods that you should implement: Convert and ConvertBack.


Here is a simple implementation of a converter that formats the Price property of the data source class to its currency representation.

    public class NumericConverter : IValueConverter  
    {  
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)  
        {  
            if (value is double)  
            {  
                var num = (double)value;  
                return num.ToString("C", culture);  
            }  
            return value;  
        }  
 
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)  
        {  
            double num;  
            if (double.TryParse(value.ToString(), out num))  
            {  
                return num;  
            }  
            return DependencyProperty.UnsetValue;  
        }  
    }  
 

The Convert method is the place to introduce you custom logic. The ConvertBack method should do the inverse of what Convert does, but Silverlight isn't making use of it, so you can leave it not implemented. Note that the data binding engine doesn’t catch exceptions by custom converters. In order to anticipate any problems with the conversion process of your data type, you should return DependencyProperty.UnsetValue. Now you can declare the value converter in the resources tag of your control like this:

<UserControl.Resources> 
        <local:NumericConverter x:Key="numConverter"/>  
</UserControl.Resources> 

 You should also associate your custom converter to the property you want to use it.

 

<TextBlock Margin="15,0,0,0" Grid.Column="1" Text="{Binding Price, Converter={StaticResource numConverter}}" /> 

 

Now if you run the application your RadComboBox should look similar to this:

ComboBox with value formatting 

It’s important to note that you can use the value converters in any control in your Silverlight application. Value converters are also very useful when dealing with DateTime types.


About the Author

Valeri Hristov

Team Lead,
Platform Team

Related Posts

Comments

Comments are disabled in preview mode.