Feeds:
Posts
Comments

Posts Tagged ‘StringFormat’

The BindingBase.StringFormat property was included with the .NET framework 4.0 and is quite a handy feature. I recently found myself going back through old projects to remove binding converters and replace their logic with the StringFormat property. There is a decent example on the MSDN here. However, I felt like expanding on it a bit so here goes.

First I have created a Person class that has some basic properties like FirstName, LastName, Age, etc. Here is the code for the Person class and enum it uses.

using System;
using System.ComponentModel;

namespace BindingStringFormat
{
     public enum Sex
     {
          male,
          female
     }

     public class Person : INotifyPropertyChanged
     {
          #region Properties

          public string FirstName
          {
               get { return _firstName; }
               set { _firstName = value; OnPropertyChanged("FirstName"); }
          }private string _firstName;

          public string LastName
          {
               get { return _lastName; }
               set { _lastName = value; OnPropertyChanged("LastName"); }
          }private string _lastName;

          public int Age
          {
               get { return _age; }
               set { _age = value; OnPropertyChanged("Age"); }
          }private int _age;

          public DateTime BirthDate
          {
               get { return _birthDate; }
               set { _birthDate = value; OnPropertyChanged("BirthDate"); }
          }private DateTime _birthDate;

          public Sex Sex
          {
               get { return _sex; }
               set { _sex = value; OnPropertyChanged("Sex"); }
          }private Sex _sex;

          #endregion

          #region Constructor(s)

          public Person() { }

          public Person(string lastName, string firstName, int age, DateTime birthDate, Sex sex)
          {
               this.FirstName = firstName;
               this.LastName = lastName;
               this.Age = age;
               this.BirthDate = birthDate;
               this.Sex = sex;
          }

          #endregion

          #region INotifyPropertyChanged Members

          public event PropertyChangedEventHandler PropertyChanged;

          void OnPropertyChanged(string propName)
          {
               if (this.PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
          }

          #endregion
     }
}

Next is the MainWindow. I have created a public Person property in the code behind and set the DataContext of the MainWindow.xaml to the Person property. Here is the code for that.

using System;
using System.Windows;

namespace BindingStringFormat
{
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
          public Person Person
          {
               get
               {
                    if (_person == null)
                         _person = new Person("Bob", "Billy", 29, new DateTime(1978, 3, 9), Sex.male);

                    return _person;
               }
               set
               {
                    _person = value;
               }
          }private Person _person;

          public MainWindow()
          {
               InitializeComponent();
               this.DataContext = Person;
          }
     }
}

Last but not least is the MainWindow.xaml which is where the StringFormat syntax lies. In this example you will notice I have bound a string, integer, enum, and date to some TextBlocks and customized their display with the StringFormat property. I especially like the ability to use StringFormat with MultiBinding, and as I said before, this should help you get rid of some now obsolete BindingConverters. Enjoy!


<Window x:Class="BindingStringFormat.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">

   <Grid Margin="25">
        <StackPanel>
             <TextBlock Margin="5">
                  <TextBlock.Text>
                       <MultiBinding StringFormat="Hello {0} {1}!">
                            <Binding Path="FirstName"/>
                            <Binding Path="LastName"/>
                       </MultiBinding>
                  </TextBlock.Text>
             </TextBlock>
             <TextBlock Text="{Binding Path=Age, StringFormat='You are {0} years old.'}" Margin="5"/>
             <TextBlock Text="{Binding Path=Sex, StringFormat='You are a {0}.'}" Margin="5"/>
             <TextBlock Text="{Binding Path=BirthDate, StringFormat='You were born on {0:MM/dd/yyyy}'}" Margin="5"/>
        </StackPanel>
   </Grid>

</Window>

Here is what you should see when you run the application:

BindingBase.StringFormat

Advertisements

Read Full Post »

Today I’m going to show how to bind a collection of objects to a TreeView while using HierarchicalDataTemplates. The root nodes in the TreeView will be Continents. Each continent will have a collection of countries, while each country will have a collection of cities. There are a few additional properties associated with each of these object. For example, cities have populations, continents have a size in square miles, etc. Here are the three classes I created for the project.

public class Continent
{
    public Continent() { }

    public string Name { get; set; }
    public int Size { get; set; }   //in sq miles
    public ObservableCollection<Country> Countries { get; set; }
}

public class Country
{
    public Country() { }

    public string Name { get; set; }
    public int Population { get; set; }
    public ObservableCollection<City> Cities { get; set; }
}

public class City
{
    public City() { }

    public string Name { get; set; }
    public int Population { get; set; }
}

Now, here is all of the code for my MainWindow.cs which contains the code for populating my ObservableCollection<Continent>.

public partial class MainWindow : Window
{
    public ObservableCollection<Continent> Continents { get; set; }

    public MainWindow()
    {
       InitializeComponent();
       Continents = CreateWorld();
       this.DataContext = Continents;
    }

    private ObservableCollection<Continent> CreateWorld()
    {
       ObservableCollection<Continent> world = new ObservableCollection<Continent>();

       Continent northAmerica = new Continent()
       {
          Name = "North America",
          Size = 9540000,
          Countries = new ObservableCollection<Country>()
          {
             new Country()
             {
                Name = "Canada",
                Population = 15000000,
                Cities = new ObservableCollection<City>()
                {
                   new City() { Name = "Ottowa", Population = 812179 },
                   new City() { Name = "Vancouver", Population = 347009 },
                   new City() { Name = "Quebec", Population = 457339 }
                }
             },
             new Country()
             {
                Name = "United States",
                Population = 3456700,
                Cities = new ObservableCollection<City>()
                {
                   new City() { Name = "Denver", Population = 124897 },
                   new City() { Name = "Boston", Population = 234659 },
                   new City() { Name = "New York", Population = 354730 },
                   new City() { Name = "Los Angeles", Population = 423100 }
                }
             },
             new Country()
             {
                Name = "Mexico",
                Population = 34000234,
                Cities = new ObservableCollection<City>()
                {
                   new City() { Name = "Mexico City", Population = 21000000 },
                   new City() { Name = "Tijuana", Population = 1594000 },
                   new City() { Name = "Puebla", Population = 1590256 }
                }
             }
          }
       };

       Continent southAmerica = new Continent()
       {
          Name = "South America",
          Size = 6879000,
          Countries = new ObservableCollection<Country>()
          {
             new Country()
             {
                Name = "Brazil",
                Population = 4210000,
                Cities = new ObservableCollection<City>()
                {
                   new City() { Name = "Sao Paulo", Population = 11500000 },
                   new City() { Name = "Rio de Janeiro", Population = 7186000 },
                   new City() { Name = "Fortaleza", Population = 2505054 }
                }
             },
             new Country()
             {
                Name = "Argentina",
                Population = 5673420,
                Cities = new ObservableCollection<City>()
                {
                   new City() { Name = "Buenos Aires", Population = 5698000 },
                   new City() { Name = "Chaco", Population = 7845000 }
                }
             }
          }
       };

       world.Add(northAmerica);
       world.Add(southAmerica);
       return world;
    }
}

Finally, here is the MainWindow.xaml that uses the HierarchicalDataTemplates to show content at each level of TreeViewItems in the tree. Please note how the multibinding utilizes Binding.StringFormat to show cities and their population in the deepest node.

<Window x:Class="TreeViewBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="331" Width="289"
        xmlns:local="clr-namespace:TreeViewBinding">

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:City}">
            <TextBlock>
                <TextBlock.Text>
                    <MultiBinding StringFormat="{}{0} ({1})">
                        <Binding Path="Name"/>
                        <Binding Path="Population"/>
                    </MultiBinding>
                </TextBlock.Text>
           </TextBlock>
       </DataTemplate>
       <HierarchicalDataTemplate DataType="{x:Type local:Country}"
                                 ItemsSource="{Binding Cities}">
            <TextBlock Text="{Binding Name}"/>
       </HierarchicalDataTemplate>
       <HierarchicalDataTemplate DataType="{x:Type local:Continent}"
                                 ItemsSource="{Binding Countries}">
            <TextBlock Text="{Binding Name}"/>
       </HierarchicalDataTemplate>
    </Window.Resources>

    <Grid>
        <TreeView x:Name="myTreeView" ItemsSource="{Binding}" Margin="0,0,12,12" />
    </Grid>

</Window>

Here is a screenshot of what you should see when you run the application. Enjoy!

Read Full Post »