Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Flexible and Powerful Data Binding with WPF, Part 2 : Page 4

Microsoft has been building data binding frameworks for years. Each one promises to solve our data binding woes forever. We're still waiting for the perfect one—but we're getting closer!




Application Security Testing: An Integral Part of DevOps

Data Formatting

Your raw data would likely benefit from some dressing up before showing it to your users. For example, they probably think that "12.5%" looks better than "0.0125."

Consider the following Sale business class which represents a sale and its details.

// C#: class Sale { // simplifed sale class // for demo purposes public Double CommisionRate { get; set; } public DateTime SaleDate { get; set; } // allowed values // R = retail, W = wholesale // G = goverment, I = internal public Char SaleType { get; set; } public Decimal Amount { get; set; } } ... // initializing the Sale class // and setting data context. Sale sale = new Sale(); sale.Amount = 1200; sale.CommisionRate = .0125; sale.SaleDate = DateTime.Now; sale.SaleType = 'W'; // wholesale this.DataContext = sale;

In VB, the equivalent code is:

' VB Class Sale ' simplifed sale class ' for demo purposes Private privateCommissionRate As Double Public Property CommissionRate() As Double Get Return privateCommissionRate End Get Set(ByVal value As Double) privateCommissionRate = value End Set End Property

Figure 3. Raw Data: Here's the raw input before applying any formatting to the bound data.
'... ' the rest of the properties omitted for brevity End Class ... ' initializing the Sale class ' and setting data context. Dim sale As New Sale() sale.Amount = 1200 sale.CommissionRate =.0125 sale.SaleDate = DateTime.Now sale.SaleType = "W"c ' wholesale Me.DataContext = sale
Figure 3 shows the raw data in the UI before applying any formats.

I'd wager that string formatting is the most common conversion operation applied to data before showing it in the UI. In this example Sale class, every property except the SaleType would look better with some formatting. To help with this common scenario, Microsoft added string formatting to WPF data binding in .NET 3.5 SP1, so now it's a snap to apply a string format using standard formatter characters such as "C" for currency, "P" for percentage, and "D" for long date. Just use the StringFormat or ContentStringFormat attributes as shown in the following example:

<!-- applies the currency format--> Text="{Binding Path=Amount,StringFormat=C}" <!-- use curly braces for more complex string formatting--> Text="{Binding Path=CommissionRate, StringFormat=2008 Rates :: {0:P}}"

Figure 4. Formatted Strings: Here's the result of applying some string formatters to the binding.
<!-- some controls have direct support for formatting--> <Button ContentStringFormat="{}{0:P}"> <sys:Double>3.14</sys:Double> </Button>

Figure 4 shows the results of applying these formats.

Data Metamorphosis

String formatting is useful but sometimes you want a bigger hammer to knock your data into shape. For that, WPF has binding converters. Once again WPF demonstrates its foresight when you examine how binding converters work.

Binding converters, implemented via the IValueConverter interface, grant you full control over your data representation as it moves through the binding pipeline. The converter sits between the data source and the data target, and offers you the opportunity to transform the data as it flows through the converter. Data moving from source to target goes through the IValueConverter.Convert method. Data moving in the reverse direction goes through the IValueConverter.ConvertBack method before arriving back at the data source.

The possibilities are tantalizing if you think about what you can do with the conversion infrastructure. Not only can you change from one data type to another but you can run code to examine the data and alter it based on various conditions. Do you want to convert a series of numbers (1, 2, 3, 4) to an ordinal representation (1st, 2nd, 3rd, 4th)? Use an Integer-to-String converter. How about changing the foreground color of a text box based on the sales amount? No problem, create a Decimal-to-SolidColorBrush converter.

The keys to the conversion process are the Convert and ConvertBack methods, both of which have the following parameters:

  • value: The original value from the data source.
  • targetType: The target property data type. In the following example, the target type would be the Brush type for the first binding and the String type for the second binding:

Background='{Binding Path=Amount, Converter={StaticResource bonusConverter}} Text= '{Binding Path=SaleDate, Converter={StaticResource saleConverter}}

  • parameter: This is an optional parameter specified in the binding.
  • culture: The current CultureInfo as determined by the .NET Framework. Useful for culturally-aware formatting.
Look at Listing 3 to see an implementation of the AmountToBonusBrushConverter, and then examine Listing 4 to see how to configure the AmountToBonusBrushConverter binding in your XAML. Pay close attention to the three properties BonusBrush, BonusGoal, and DefaultBrush in the converter class, which permit customization of the converter in the page XAML.

Figure 5. Converters in Action: The BonusBrushConverter has been applied to the second TextBlock in the UI.
Figure 5 shows the results in the UI. As you can see in the screenshot, the first and third TextBlocks are painted the default color (set as Yellow in the following XAML block). The second TextBlock is painted green because the underlying value is greater than the BonusGoal amount of 4000:

<local:AmountToBonusBrushConverter x:Key="bonusConverter" BonusBrush='LightGreen' BonusGoal='4000' DefaultBrush='Yellow' />

As a final example here's a short snippet that shows how to convert the SaleType char value to a more readable string.

// C#: public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { char candidate = (char)value; switch (candidate){ case 'R': return "Retail"; break; case 'W': return "Wholesale"; break; } return "Unknown sale type"; } ' VB: Public Function Convert(ByVal value As Object, _ ByVal targetType As Type, _ ByVal parameter As Object, _ ByVal culture As CultureInfo) As Object _ Implements IValueConverter.Convert Dim candidate As Char = CChar(value) Select Case candidate Case "R"c Return "Retail" Case "W"c Return "Wholesale" End Select Return "Unknown sale type" End Function

What's Left?

I hope this article series has been a good starting point on your journey to data binding mastery. I've spent a few pages covering the wonders of the WPF binding world—but I'm not finished. There is still a mountain of binding topics left to cover. Data templates, data selectors, data triggers, data providers, MultiBinding converters, and managing hierarchical data are some of the essential topics you should explore. I also haven't covered the CollectionView's sorting, filtering, grouping, and navigation abilities, or looked at list binding, or at any of the ItemsControls elements. I hope that you see the power and potential of WPF binding by now and are ready to learn more.

Walt Ritscher has trained thousands of corporate developers during the last twelve years. An active speaker, his teaching schedule has taken him throughout the world providing developer training at corporations, universities, and software conferences. He has collaborated on several books and videos published for the developer market, including early adopter .NET courses at Microsoft Press. Walt is currently consulting and teaching .NET and WPF classes for Wintellect. Walt's industry expertise has placed him on various national technology advisory boards. He is also deeply involved in the local developer community-founding the .NET Developers Association in Redmond, WA. Walt has accumulated plenty of experience as a developer and is currently a Microsoft MVP and a member of the Silverlight Insiders. As a web programmer he has worked on numerous projects, including EPA sites and the Microsoft Community Starter Kit.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.
Thanks for your registration, follow us on our social networks to keep up-to-date