Follow @PDSAInc June 2011 - Posts - Paul Sheriff's Blog for the Real World

Paul Sheriff's Blog for the Real World

This blog is to share my tips and tricks garnered over 25+ years in the IT industry

Paul's Favorites

June 2011 - Posts

Sort Data in Windows Phone using Collection View Source

When you write a Windows Phone application you will most likely consume data from a web service somewhere. If that service returns data to you in a sort order that you do not want, you have an easy alternative to sort the data without writing any C# or VB code. You use the built-in CollectionViewSource object in XAML to perform the sorting for you. This assumes that you can get the data into a collection that implements the IEnumerable or IList interfaces.

For this example, I will be using a simple Product class with two properties, and a list of Product objects using the Generic List class. Try this out by creating a Product class as shown in the following code:

public class Product
{
  public Product(int id, string name)
  {
    ProductId = id;
    ProductName = name;
  }

  public int ProductId { get; set; }
  public string ProductName { get; set; }
}

Create a collection class that initializes a property called DataCollection with some sample data as shown in the code below:

public class Products : List<Product>
{
  public Products()
  {
    InitCollection();
  }

  public List<Product> DataCollection { get; set; }

  List<Product> InitCollection()
  {
    DataCollection = new List<Product>();

    DataCollection.Add(new Product(3,
       "PDSA .NET Productivity Framework"));
    DataCollection.Add(new Product(1,
       "Haystack Code Generator for .NET"));
    DataCollection.Add(new Product(2,
       "Fundamentals of .NET eBook"));

    return DataCollection;
  }
}

Notice that the data added to the collection is not in any particular order. Create a Windows Phone page and add two XML namespaces to the Page.

xmlns:scm="clr-namespace:System.ComponentModel;assembly=System.Windows"
xmlns:local="clr-namespace:WPSortData"

The 'local' namespace is an alias to the name of the project that you created (in this case WPSortData). The 'scm' namespace references the System.Windows.dll and is needed for the SortDescription class that you will use for sorting the data. Create a phone:PhoneApplicationPage.Resources section in your Windows Phone page that looks like the following:

<phone:PhoneApplicationPage.Resources>
  <local:Products x:Key="products" />
  <CollectionViewSource x:Key="prodCollection"
      Source="{Binding Source={StaticResource products},
                       Path=DataCollection}">
    <CollectionViewSource.SortDescriptions>
      <scm:SortDescription PropertyName="ProductName"
                           Direction="Ascending" />
    </CollectionViewSource.SortDescriptions>
  </CollectionViewSource>
</phone:PhoneApplicationPage.Resources>

The first line of code in the resources section creates an instance of your Products class. The constructor of the Products class calls the InitCollection method which creates three Product objects and adds them to the DataCollection property of the Products class. Once the Products object is instantiated you now add a CollectionViewSource object in XAML using the Products object as the source of the data to this collection. A CollectionViewSource has a SortDescriptions collection that allows you to specify a set of SortDescription objects. Each object can set a PropertyName and a Direction property. As you see in the above code you set the PropertyName equal to the ProductName property of the Product object and tell it to sort in an Ascending direction.

All you have to do now is to create a ListBox control and set its ItemsSource property to the CollectionViewSource object. The ListBox displays the data in sorted order by ProductName and you did not have to write any LINQ queries or write other code to sort the data!

<ListBox
   ItemsSource="{Binding Source={StaticResource prodCollection}}"
   DisplayMemberPath="ProductName" />

Summary

In this blog post you learned that you can sort any data without having to change the source code of where the data comes from. Simply feed the data into a CollectionViewSource in XAML and set some sort descriptions in XAML and the rest is done for you! This comes in very handy when you are consuming data from a source where the data is given to you and you do not have control over the sorting.

NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Sort Data in Windows Phone using Collection View Source” from the drop down list.

Good Luck with your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!

Synch a ComboBox in Silverlight with Foreign Keys

In most database applications you will have foreign keys to express a relationship between one table and another. Many times this takes the form of a lookup table where you want the user to pick from a selection of items such as an Employee Type for an Employee record. You don’t want to have the user remember a number such as 1, 2, or 3, but instead they will pick from a list of the description that corresponds to these numbers such as “Manager”, “Project Manager”, or Employee. While you want to display these descriptions in a ComboBox, like that shown in Figure 1, you want to store the Employee Type ID number into your Employee table to make the data smaller and make it more efficient to join between the two tables.

In Figure 1 you see a DataGrid of Employee object and each employee has been assigned an EmployeeTypeId. As you click on each Employee object in the DataGrid you display the data using data binding in the text boxes at the bottom of the screen. You also have a ComboBox where each row is an EmployeeType object. Since the Employee object only has the EmployeeTypeId you need to position the ComboBox to that appropriate value so it can update the description as you move through the Employee objects. This blog post will discuss how to accomplish this using data binding in Silverlight.

Figure 1: A ComboBox is used to display related values based on a foreign key

Figure 1: A ComboBox is used to display related values based on a Foreign Key

To keep things simple for this sample, I will not be using a database, but instead will just be hard coding some values for the Employee and EmployeeType objects. Let’s take a look at the classes that make up this sample.

The EmployeeType Class

The EmployeeType class is very simple with just an EmployeeTypeId property and and EmpType property. The constructor will pass in an id and a description to assign to the EmpType property. Within this same file there is an EmployeeTypes collection class. This collection class uses a Generic List.

public class EmployeeType
{
  public EmployeeType(int id, string empType)
  {
    EmployeeTypeId = id;
    EmpType = empType;
  }

  public int EmployeeTypeId { get; set; }
  public string EmpType { get; set; }
}

public class EmployeeTypes : List<EmployeeType>
{
}

The Employee Class

The Employee class has three properties; EmployeeId, Name, and EmployeeTypeId. The constructor allows you to pass in all three of these values to set the appropriate properties. A Generic List class is used for a collection class of Employee objects.

public class Employee
{
  public Employee(int id, string name, int empTypeId)
  {
    EmployeeId = id;
    Name = name;
    EmployeeTypeId = empTypeId;
  }

  public int EmployeeId { get; set; }
  public string Name { get; set; }
  public int EmployeeTypeId { get; set; }
}

public class Employees : List<Employee>
{
}

The EmployeeViewModel Class

For this sample you will also need a ViewModel class. In this class is where you will create a list of Employee objects and EmployeeType objects. This class will be used for the binding to the XAML in the Employee User Control.

In this class you will use two Dependency Properties for the collection of Employee objects and the collection of EmployeeType objects. A Dependency Property is simply a property that stores its data into an internal structure and not into a private variable like a simple property you might create. In addition, a Dependency Property also implements the INotifyPropertyChanged event so if the value changes a PropertyChanged event is raised to inform any object bound to it that it needs to update its value. To use Dependency Properties your class must inherit from DependencyObject.

The EmployeeViewModel class has one method to load a collection of Employee objects into the EmployeeCollection property. It also has a method to load a collection of EmployeeType objects into the EmployeeTypesCollection property. The constructor of this EmployeeViewModel class calls both of these methods so the properties will be loaded when an instance of this class is created.

public class EmployeeViewModel : DependencyObject
{
  public EmployeeViewModel()
  {
    LoadEmployees();
    LoadEmployeeTypes();
  }

  public EmployeeTypes EmployeeTypesCollection
  {
    get { return (EmployeeTypes)GetValue(
                         EmployeeTypesCollectionProperty); }
    set { SetValue(EmployeeTypesCollectionProperty, value); }
  }

  public static readonly DependencyProperty
     EmployeeTypesCollectionProperty =
      DependencyProperty.Register("EmployeeTypesCollection",
       typeof(EmployeeTypes), typeof(EmployeeViewModel), null);

  public Employees EmployeeCollection
  {
    get { return (Employees)GetValue(EmployeeCollectionProperty); }
    set { SetValue(EmployeeCollectionProperty, value); }
  }

  public static readonly DependencyProperty
    EmployeeCollectionProperty =
      DependencyProperty.Register("EmployeeCollection",
       typeof(Employees), typeof(EmployeeViewModel), null);

  public void LoadEmployeeTypes()
  {
    EmployeeTypesCollection = new EmployeeTypes();
    EmployeeTypesCollection.Add(new EmployeeType(1, "Manager"));
    EmployeeTypesCollection.Add(new EmployeeType(2,
           "Project Manager"));
    EmployeeTypesCollection.Add(new EmployeeType(3, "Employee"));
  }

  public void LoadEmployees()
  {
    EmployeeCollection = new Employees();
    EmployeeCollection.Add(new Employee(1,
      "Michael Krasowski", 1));
    EmployeeCollection.Add(new Employee(2, "John Kuhn", 2));
    EmployeeCollection.Add(new Employee(3, "Jim Ruhl", 3));
    EmployeeCollection.Add(new Employee(4, "Russ Marzolf", 3));
    EmployeeCollection.Add(new Employee(4, "John Brongo", 3));
  }
}

The XAML

Now that you have all of your classes created you are now ready to create the user interface shown in Figure 1. You will add a DataGrid, some text block and text box controls, and a combo box. You will assign the DataGrid the name “grdData”.

You will need to have your User Control create an instance of the ViewModel class. You do this by adding an XML namespace that points at your project and assign an alias of “vm”.

<UserControl x:Class="SLComboBox.MainPage"
        ...
        xmlns:vm="clr-namespace:SLComboBox"
        ...>

You can then create an instance of the EmployeeViewModel class in the UserControl.Resources element of your User Control using the following syntax. You will assign this class a key (a variable name) of “viewModel”.

<UserControl.Resources>
  <vm:EmployeeViewModel x:Key="viewModel" />
</UserControl.Resources>

Now it is time for you to bind the DataGrid to the EmployeeCollection property in your ViewModel class. To your DataGrid element you can add the following ItemsSource property. This syntax uses a typical Binding where the source of the data is the StaticResource “viewModel”. The path is the EmployeeCollection dependency property.

<sdk:DataGrid
        AutoGenerateColumns="True"
        Name="grdData"
        ItemsSource="{Binding Source={StaticResource viewModel},
                              Path=EmployeeCollection}" />

The TextBox controls on this form are contained within a Grid control. This Grid’s DataContext property is bound to the SelectedItem property of the DataGrid named “grdData” on this user control. Since all of TextBox controls are contained within this Grid control, you only need to specify the {Binding Path=[PROPERTY]} within the Text property of each text box. Check the sample (instructions for download are at the end of this blog post) for the complete syntax.

<Grid Grid.Row="1"
      DataContext="{Binding ElementName=grdData,
                            Path=SelectedItem}">

Bind the ComboBox

Finally it is time to create the bindings for the ComboBox. The data to load into the ComboBox will come from the EmployeeViewModel class and the property called EmployeeTypesCollection within that object. So the ItemsSource property will be bound to that object and that property. You will set the DisplayMemberPath to “EmpType” which is the property that has the employee type description. In order to position the ComboBox when you change to a different selected item in the DataGrid you need to also bind the SelectedValuePath and SelectedValue properties.

The SelectedValuePath is set to the EmployeeTypeId property in the EmployeeType object. The SelectedValue property if set with a value like 1, 2 or 3 will force the ComboBox to set the selected index to the value that matches what is put into this property. You will need to bind this property to the EmployeeTypeId property in the Employee object that comes from the DataGrid. You use an ElementName binding to the “grdData” DataGrid and set the Path to “SelectedItem.EmployeeTypeId”. Remember that when you click on the DataGrid, the SelectedItem property is set to the current Employee object. The Employee object contains a EmployeeTypeId property that is set to a value like 1, 2, or 3. This is what sets the SelectedValue each time you move through the DataGrid. This then causes the ComboBox to reposition to the appropriate employee type description.

<ComboBox
          DisplayMemberPath="EmpType"
          SelectedValuePath="EmployeeTypeId"
          SelectedValue="{Binding
                          ElementName=grdData,
                          Path=SelectedItem.EmployeeTypeId}"
          ItemsSource="{Binding Source={StaticResource viewModel},
                                Path=EmployeeTypesCollection}" />

Summary

In this blog post you learned how to keep a ComboBox in synch with a DataGrid as you move through related data. As with most things in XAML, it is all about creating classes with properties and methods to hold data, then simply binding to the appropriate properties to display that data. In the case of a ComboBox you just need to set the SelectedValuePath and the SelectedValue attributes to have it automatically update when the data in a related object changes.

NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Synch a ComboBox in Silverlight with Foreign Keys” from the drop down list.

Good Luck with your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!

 

Synch a ComboBox in WPF with Foreign Keys

In most database applications you will have foreign keys to express a relationship between one table and another. Many times this takes the form of a lookup table where you want the user to pick from a selection of items such as an Employee Type for an Employee record. You don’t want to have the user remember a number such as 1, 2, or 3, but instead they will pick from a list of the description that corresponds to these numbers such as “Manager”, “Project Manager”, or Employee. While you want to display these descriptions in a ComboBox, like that shown in Figure 1, you want to store the Employee Type ID number into your Employee table to make the data smaller and make it more efficient to join between the two tables.

In Figure 1 you see a DataGrid of Employee object and each employee has been assigned an EmployeeTypeId. As you click on each Employee object in the DataGrid you display the data using data binding in the text boxes at the bottom of the screen. You also have a ComboBox where each row is an EmployeeType object. Since the Employee object only has the EmployeeTypeId you need to position the ComboBox to that appropriate value so it can update the description as you move through the Employee objects. This blog post will discuss how to accomplish this using data binding in WPF.

Figure 1: A ComboBox is used to display related values based on a Foreign Key

Figure 1: A ComboBox is used to display related values based on a Foreign Key

To keep things simple for this sample, I will not be using a database, but instead will just be hard coding some values for the Employee and EmployeeType objects. Let’s take a look at the classes that make up this sample.

The EmployeeType Class

The EmployeeType class is very simple with just an EmployeeTypeId property and and EmpType property. The constructor will pass in an id and a description to assign to the EmpType property. Within this same file there is an EmployeeTypes collection class. This collection class uses a Generic List.

public class EmployeeType
{
  public EmployeeType(int id, string empType)
  {
    EmployeeTypeId = id;
    EmpType = empType;
  }

  public int EmployeeTypeId { get; set; }
  public string EmpType { get; set; }
}

public class EmployeeTypes : List<EmployeeType>
{
}

The Employee Class

The Employee class has three properties; EmployeeId, Name, and EmployeeTypeId. The constructor allows you to pass in all three of these values to set the appropriate properties. A Generic List class is used for a collection class of Employee objects.

public class Employee
{
  public Employee(int id, string name, int empTypeId)
  {
    EmployeeId = id;
    Name = name;
    EmployeeTypeId = empTypeId;
  }

  public int EmployeeId { get; set; }
  public string Name { get; set; }
  public int EmployeeTypeId { get; set; }
}

public class Employees : List<Employee>
{
}

The EmployeeViewModel Class

For this sample you will also need a ViewModel class. In this class is where you will create a list of Employee objects and EmployeeType objects. This class will be used for the binding to the XAML in the Employee window.

In this class you will use two Dependency Properties for the collection of Employee objects and the collection of EmployeeType objects. A Dependency Property is simply a property that stores its data into an internal structure and not into a private variable like a simple property you might create. In addition, a Dependency Property also implements the INotifyPropertyChanged event so if the value changes a PropertyChanged event is raised to inform any object bound to it that it needs to update its value. To use Dependency Properties your class must inherit from DependencyObject.

The EmployeeViewModel class has one method to load a collection of Employee objects into the EmployeeCollection property. It also has a method to load a collection of EmployeeType objects into the EmployeeTypesCollection property. The constructor of this EmployeeViewModel class calls both of these methods so the properties will be loaded when an instance of this class is created.

public class EmployeeViewModel : DependencyObject
{
  public EmployeeViewModel()
  {
    LoadEmployees();
    LoadEmployeeTypes();
  }

  public EmployeeTypes EmployeeTypesCollection
  {
    get { return (EmployeeTypes)GetValue(
                         EmployeeTypesCollectionProperty); }
    set { SetValue(EmployeeTypesCollectionProperty, value); }
  }

  public static readonly DependencyProperty
     EmployeeTypesCollectionProperty =
      DependencyProperty.Register("EmployeeTypesCollection",
       typeof(EmployeeTypes), typeof(EmployeeViewModel), null);

  public Employees EmployeeCollection
  {
    get { return (Employees)GetValue(EmployeeCollectionProperty); }
    set { SetValue(EmployeeCollectionProperty, value); }
  }

  public static readonly DependencyProperty
    EmployeeCollectionProperty =
      DependencyProperty.Register("EmployeeCollection",
       typeof(Employees), typeof(EmployeeViewModel), null);

  public void LoadEmployeeTypes()
  {
    EmployeeTypesCollection = new EmployeeTypes();
    EmployeeTypesCollection.Add(new EmployeeType(1, "Manager"));
    EmployeeTypesCollection.Add(new EmployeeType(2,
           "Project Manager"));
    EmployeeTypesCollection.Add(new EmployeeType(3, "Employee"));
  }

  public void LoadEmployees()
  {
    EmployeeCollection = new Employees();
    EmployeeCollection.Add(new Employee(1,
      "Michael Krasowski", 1));
    EmployeeCollection.Add(new Employee(2, "John Kuhn", 2));
    EmployeeCollection.Add(new Employee(3, "Jim Ruhl", 3));
    EmployeeCollection.Add(new Employee(4, "Russ Marzolf", 3));
    EmployeeCollection.Add(new Employee(4, "John Brongo", 3));
  }
}

The XAML

Now that you have all of your classes created you are now ready to create the user interface shown in Figure 1. You will add a DataGrid, some text block and text box controls, and a combo box. You will assign the DataGrid the name “grdData”.

You will need to have your window create an instance of the ViewModel class. You do this by adding an XML namespace that points at your project and assign an alias of “vm”.

<Window x:Class="WPFComboBox.MainWindow"
        ...
        xmlns:vm="clr-namespace:WPFComboBox"
        ...>

You can then create an instance of the EmployeeViewModel class in the Window.Resources element of your Window using the following syntax. You will assign this class a key (a variable name) of “viewModel”.

<Window.Resources>
  <vm:EmployeeViewModel x:Key="viewModel" />
</Window.Resources>

Now it is time for you to bind the DataGrid to the EmployeeCollection property in your ViewModel class. To your DataGrid element you can add the following ItemsSource property. This syntax uses a typical Binding where the source of the data is the StaticResource “viewModel”. The path is the EmployeeCollection dependency property.

<DataGrid AutoGenerateColumns="True"
          Name="grdData"
          ItemsSource="{Binding Source={StaticResource viewModel},
                                Path=EmployeeCollection}" />

The TextBox controls on this form are contained within a Grid control. This Grid’s DataContext property is bound to the SelectedItem property of the DataGrid named “grdData” on this window. Since all of TextBox controls are contained within this Grid control, you only need to specify the {Binding Path=[PROPERTY]} within the Text property of each text box. Check the sample (instructions for download are at the end of this blog post) for the complete syntax.

<Grid Grid.Row="1"
      DataContext="{Binding ElementName=grdData,
                            Path=SelectedItem}">

Bind the ComboBox

Finally it is time to create the bindings for the ComboBox. The data to load into the ComboBox will come from the EmployeeViewModel class and the property called EmployeeTypesCollection within that object. So the ItemsSource property will be bound to that object and that property. You will set the DisplayMemberPath to “EmpType” which is the property that has the employee type description. In order to position the ComboBox when you change to a different selected item in the DataGrid you need to also bind the SelectedValuePath and SelectedValue properties.

The SelectedValuePath is set to the EmployeeTypeId property in the EmployeeType object. The SelectedValue property if set with a value like 1, 2 or 3 will force the ComboBox to set the selected index to the value that matches what is put into this property. You will need to bind this property to the EmployeeTypeId property in the Employee object that comes from the DataGrid. You use an ElementName binding to the “grdData” DataGrid and set the Path to “SelectedItem.EmployeeTypeId”. Remember that when you click on the DataGrid, the SelectedItem property is set to the current Employee object. The Employee object contains a EmployeeTypeId property that is set to a value like 1, 2, or 3. This is what sets the SelectedValue each time you move through the DataGrid. This then causes the ComboBox to reposition to the appropriate employee type description.

<ComboBox
          DisplayMemberPath="EmpType"
          SelectedValuePath="EmployeeTypeId"
          SelectedValue="{Binding
                          ElementName=grdData,
                          Path=SelectedItem.EmployeeTypeId}"
          ItemsSource="{Binding Source={StaticResource viewModel},
                                Path=EmployeeTypesCollection}" />

Summary

In this blog post you learned how to keep a ComboBox in synch with a DataGrid as you move through related data. As with most things in XAML, it is all about creating classes with properties and methods to hold data, then simply binding to the appropriate properties to display that data. In the case of a ComboBox you just need to set the SelectedValuePath and the SelectedValue attributes to have it automatically update when the data in a related object changes.

NOTE: You can download this article and many samples like the one shown in this blog entry at my website. http://www.pdsa.com/downloads. Select “Tips and Tricks”, then “Synch a ComboBox in WPF with Foreign Keys” from the drop down list.

Good Luck with your Coding,
Paul Sheriff

** SPECIAL OFFER FOR MY BLOG READERS **
We frequently offer a FREE gift for readers of my blog. Visit http://www.pdsa.com/Event/Blog for your FREE gift!

 

Posted: Jun 08 2011, 12:09 PM by psheriff | with 2 comment(s)
Filed under: ,
More Posts