June 2011 - Posts
Introduction
ListBox grouping is one of the features that Silverlight did not inherit from WPF, even though is a common requirement. Here we present a very simple yet powerful way to implement grouping in the ListBox control that also allows subgrouping and sorting.
This approach is supported on traditional Silverlight applications, and also on Windows Phone 7 applications.
The problem
Although WPF supports grouping for the ListBox control, Silverlight doesn’t. The developer is restricted to load a plain, unstructured collection of items. However, the hierarchical scenario is very common in applications that display different types of data.
The solution
To overcome this issue, we will use a Binding Converter, which will group the items internally, adding to the ListBox a ContentControl element with a specific template, for each group header it creates, and a ContentControl with another template, for each item on each group it creates. Sounds complicated? It’s not, let’s do it!
Suppose you have a list of items that you want to display hierarchically. You proceed by creating the ListBox and binding its ItemsSource dependency property to the collection of items. In XAML it would look like this:
<ListBox x:Name="List" ItemsSource="{Binding}"/>
And the code-behind would look like this:
IEnumerable<ItemType> items = ...;
List.DataContext = items;
At this point, the ListBox shows the list of items without any structure. Now, let’s add a Converter to the binding. A converter is an instance of a class that implements IValueConterter, which has only two methods: Convert and ConvertBack. Before Silverlight binds the collection of items, it will call the Convert function, allowing us to transform the data as we want. The ConvertBack method will never be called for this type of binding, since this is a OneWay binding. For more information about data bindings, see http://msdn.microsoft.com/en-us/library/ms752347.aspx
So, all we need is a new class that implements the IValueConverter interface. In this case, “PetGrouper”:
public class PetGrouper : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// ...
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Because ConvertBack will never be called, we can leave it untouched, throwing a NotImplementedException. For the Convert method, we already know the type of data we are assigning to the DataContext. That same instance comes as an object in the value parameter. We can ignore the rest of the parameters in this case.
Next, we have to group and sort the data. For each group we create, we will add a control with a template designed for headers, and for each one of its items, we will add a control with a template designed for items.
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
IEnumerable<Pet> pets = value as IEnumerable<Pet>;
List<ContentControl> groupedPets = new List<ContentControl>();
foreach (IGrouping<string, Pet> animal in pets.GroupBy(x => x.Animal).OrderBy(x => x.Key))
{
groupedPets.Add(new ContentControl() { Content = animal.Key, ContentTemplate = App.Current.Resources["AnimalTemplate"] as DataTemplate });
foreach (Pet pet in animal.OrderBy(x => x.Breed))
{
groupedPets.Add(new ContentControl() { Content = pet, ContentTemplate = App.Current.Resources["BreedTemplate"] as DataTemplate });
}
}
return groupedPets;
}
AnimalTemplate and BreedTemplate are resources in App.xaml. In this example we are grouping the pets by animal type, sorting the groups by animal type name, and sorting each item on the groups by breed name.
The type IGrouping<string, Pet>, describes a list of groups whose headers (“keys”) are strings, and each one of them is populated by pets. The Key type may vary for different scenarios. For example if we were grouping by vertebrates and invertebrates, the Key would be a bool value, and we would have to add a significant text to the header content, so it doesn’t show “True” and “False”.
As you may note, this approach is unrestricted as to how the data is shown. You can group items on several levels, sort the items by any property, and even sort the groups themselves.
Finally, we have to link our converter to the binding. This is done by adding a resource in the page containing the ListBox, and linking the binding to that resource:
<UserControl.Resources>
<local:PetGrouper x:Key="PetValueConverter"></local:PetGrouper>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<ListBox x:Name="List" ItemsSource="{Binding Converter={StaticResource PetValueConverter}}" />
</Grid>
Sample application
Here is a sample application that implements grouping and sorting in a ListBox.
The solution contains two projects: a traditional browser application, and a Windows Phone 7 application.
Conclusion
Even the Silverlight ListBox does not have native support for structured data; we can use a binding converter to customize the binding, creating the layout that best fits our case. We have seen that this approach is simple, straightforward, and yet incredible powerful, and it’s supported on classic Silverlight applications and Phone applications.
Alfonso Cora
Hi,
We have seen in the previous post how to consume OData services from Windows Phone 7, this time I want to show you how to do it from an iPhone.
1. To consume OData from an iPhone App I have used a library called “OData Client for Objective-C”. It can be downloaded from here: http://odataobjc.codeplex.com/
The library contains some examples using the Netflix Catalog that can help you get familiar with more advanced stuffs than what are going to be explained in this article.
2. Once you downloaded the library the first thing you have to do on XCode is to add the references to the OData library.
This is done by accessing the Project Properties:

3. On the Build tab of the Properties window locate the section “Search Paths” and add the following reference in “Header Search Paths” and “Library Search Paths”:

Also make sure that you selected the recursive checkbox to both paths.
4. After both paths are added you need to add the library to the Frameworks folder of the solution, looking into the file system for the libMSODataLib.a located at this relative path inside the OData SDK folder: “/framework/bin/odatalib/lib/iPhoneSimulatorLibs/iPhone_Simulator_4.1/release/libMSODataLib.a”

5. After that’s done you will have the library for the project ready to be used.
6. Creating the proxy class.
To connect to OData you need to generate the proxy class. To do that open terminal, navigate to the folder where the odatagen executable is located and run this command:
./odatagen /uri=http://domain.com/YourService.svc /out=/Development/odataproxy
On the folder odataproxy you will find the generated proxy, now you need to import the “.h” and “.m” file into the classes folder of the project.
7. After that’s ready, use the proxy to connect to the server at any of the classes.
In this example, I assume that the proxy generated is called CustomersEntities.
With the next line you will have the proxy connected to the server:
CustomersEntities *proxy = [[CustomersEntities alloc]initWithUri:@”URL TO SERVICE” credential:nil];
And to get data simply do the following:
NSArray *customers;
customers = [proxy Customers];
With this example you will have a list of Customers loaded using OData services.
Of course, you can run much more complex queries using OData but that’s not the main focus of this article.
Here is a screen capture of my iPhone App consuming OData :)

Sebastián Rodríguez
Hi,
In this article I want to show you quickly how easy, funny and powerful is to consume OData services in Windows Phone 7.
I am going to take this article from Microsoft as reference, adding screenshots and comments about the process.
So, in order to write your first Windows Phone 7 application that consumes OData, you may want to follow the following steps:
1. Download Windows Phone 7 OData Client libraries.
http://go.microsoft.com/fwlink/?LinkId=207900
The OData client library for Windows Phone generates HTTP requests to a data service that supports OData and transforms the entries in the response feed into objects on the client. Using this client, you can bind Windows Phone controls, such as ListBox or TextBox, to an instance of a DataServiceCollection class that contains an OData data feed. This class handles the events raised by the controls to keep the DataServiceContext class synchronized with changes that are made to data in the controls. For more information about using the OData protocol with Windows Phone applications, see Open Data Protocol (OData) Overview for Windows Phone.
Pasted from <http://msdn.microsoft.com/en-us/library/gg521145(v=vs.92).aspx>

2. Create a new Windows Phone application. In Solution Explorer, right-click the Solution, point to Add, and then select New Project.
3. In the Add New Project dialog box, select Silverlight for Windows Phone from the Installed Templates pane, and then select the Windows Phone Application template. Write a name for the project (e.g. 'WP7ODataSampleApp')

4. Click OK. This creates the application for Silverlight.
5. Generate the proxy classes by running the command datasvcutil.exe included in the OData client libraries ZIP.
Go to Start->Run
Write 'cmd' and press Enter

Within the console, move to the directory where you have downloaded the OData client libraries.
For instance, '> cd D:\pablop\Documents\WP7\odata client libraries'

Then, run the datasvcutil.exe in order to generate the local proxy for the exposed OData services.
For the purposes of this article we are going to use the Northwind public OData services, exposed at the following Url: http://services.odata.org/Northwind/Northwind.svc
(you can take this as an example and actually use whatever OData service you have access to)
Take the following command line as reference to generate the proxy:
datasvcutil /uri:http://services.odata.org/Northwind/Northwind.svc/ /out:.\NorthwindModel.cs /Version:2.0 /DataServiceCollection

You can check the generated proxy class file by running a 'dir *.cs' command, like shown below:

6. Move the generated file to the directory where the WP7 solution is located. You can do that just with Windows Explorer.
7. Add the file by selecting it from Project -> Add Existing item … or just by clicking on 'Show All Files' in Solution Explorer, right clicking then on the new .cs file and choosing 'Include in Project'


8. Add a reference in the project to the System.Data.Services.Client.dll included in the OData Client library ZIP.


9. In the project, double-click the MainPage.xaml file.
Add the following attributes to your phone:PhoneApplicationPage node:
xmlns:my="clr-namespace:NorthwindModel"
d:DataContext="{d:DesignInstance Type=my:Customer, CreateList=True}"
Loaded="PhoneApplicationPage_Loaded">
Take the following xaml as a reference:
<phone:PhoneApplicationPage
x:Class="ODataNorthwindPhone.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:my="clr-namespace:NorthwindModel"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
d:DataContext="{d:DesignInstance Type=my:Customer, CreateList=True}"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="Northwind Sales"
Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Customers" Margin="9,-7,0,0"
Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding Path=CompanyName}" TextWrapping="NoWrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding Path=ContactName}" TextWrapping="NoWrap"
Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
<TextBlock Text="{Binding Path=Phone}" TextWrapping="NoWrap" Margin="12,-6,12,0"
Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
The 'd:DataContext' line above allows to create data bindings at design time for a data context that is assigned at run time. This way you will be able to see sample data within the Silverlight Visual Designer in Visual Studio and Expression Blend. Obviously this line is not required but recommended :).
10. Replace ContentPanel grid with something like this:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="MainListBox" Margin="0,0,-12,0" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding Path=CompanyName}" TextWrapping="NoWrap"
Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding Path=ContactName}" TextWrapping="NoWrap"
Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
<TextBlock Text="{Binding Path=Phone}" TextWrapping="NoWrap" Margin="12,-6,12,0"
Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
11. Open MainPage.xml and add the following namespaces:
using System.Data.Services.Client;
using NorthwindModel;
12. Add the following declarations to the MainPage class:
private DataServiceContext northwind;
private readonly Uri northwindUri =
new Uri("http://services.odata.org/Northwind/Northwind.svc/");
private DataServiceCollection<Customer> customers;
private readonly Uri customersFeed = new Uri("/Customers", UriKind.Relative);
13. Add the following PhoneApplicationPage_Loaded method to the MainPage class:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
// Initialize the context and the binding collection
northwind = new DataServiceContext(northwindUri);
customers = new DataServiceCollection<Customer>(northwind);
// Register for the LoadCompleted event.
customers.LoadCompleted
+= new EventHandler<LoadCompletedEventArgs>(customers_LoadCompleted);
// Load the customers feed by using the URI.
customers.LoadAsync(customersFeed);
}
The above code initializes the binding collection and registers the method 'customers_LoadCompleted' (to be created on next step) to be called when collection has been loaded.
Remember that in Silverlight, all data must be retrieved asynchronously.
14. Now, let's handle the LoadCompleted event by adding the customers_LoadCompleted method. Take the following code as reference:
void customers_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
if (e.Error == null)
{
// Handling for a paged data feed.
if (customers.Continuation != null)
{
// Automatically load the next page.
customers.LoadNextPartialSetAsync();
}
else
{
// Set the data context of the listbox control to the sample data.
this.LayoutRoot.DataContext = customers;
}
}
else
{
MessageBox.Show(string.Format("An error has occurred: {0}", e.Error.Message));
}
}
When the LoadCompleted event is handled, the following operations are performed if the request returns successfully:
o The LoadNextPartialSetAsync method of the DataServiceCollection object is called to load subsequent results pages, as long as the Continuation property of the DataServiceCollection object returns a value.
o The collection of loaded Customer objects is bound to the DataContext property of the element that is the master binding object for all controls in the page.
o Now, we are ready to test our first WP7 OData sample application. Just press F5 and wait for the emulator to be loaded and run our app. (this typically takes several secs)



16. As shown above, the main page is retrieving customers from OData.
Hope you find this article useful in order to start to play and/or build robust solutions on top of OData and Windows Phone 7, two extremely powerful platforms. Better together, for sure! :)
PP.
In some cases it is necessary to hide some items from the side menu according to the CRM user’s assigned role. To do this we need to modify the SiteMap from the CRM.
The example given in this post is done on CRM 2011 but it also applies to CRM 4.
We are going to see:
· How to hide items from the Settings section.
· How to hide the whole Settings area.
Firstly, we are going to export the CRM SiteMap as follows:
Go to Settings > Solutions >
Create a new solution.

Complete data.

In the “Add Existing” menu we select “SiteMap” option and then “Save and Close”.

Once we create the solution we select and export it, by clicking the “Export” button.
Click “Next”

Select “Customizations”

Mark the “Unmaneged” choice. Click “Export” and save the file .zip.

When extracting the zip we find the customizations.xml file which contains the customizations from our CRM, just the ones from the “SiteMap” in this case.
Inside the <SiteMap> node is the complete structure from the side menu.
The privilege level the user has over the entity assigned to the menu item means what is going to determine it to be shown for some users but not for others.
Example:

In this case only those roles having the “Read” permission over the “Solution” entity will be able to see this menu item. This compels us to attach a role to an entity in order to determine if the menu item is visible or not.
So we have two options: to create an entity just to define the visibility of the menu item, or to use an already created entity not working with it in our solution, for example “Solution”.
To determine which permissions has a role over an entity we go to Settings > Administration > Security Roles

In the role properties window we can assign or remove the permissions over the entities. In this case we remove the “Read” permission from the “Solution” entity.
In this example the users of the role “User” won’t have the “Business Management” option visible inside the “Settings” menu.
Keep in mind the privileges are set over the <SubArea> nodes, if it necessary to hide the “Settings” menu we need to hide all the <SubArea> nodes.
In CRM 4.0 by default we do not have a Picklist where to select multiple items. In the post below I am giving the details to get this functionality.
Firstly, we create a Picklist with all values.

Then, we create a text field which is going to store the selected values from the multi-value Picklist.

Using the following script we extend the Picklist functionality to allow it to select multiple values. We change new_mypicklist and new_mypicklistvalue by the names of previously created attributes.
The code was extracted from this post
var PL = crmForm.all.new_mypicklist;
var PLV = crmForm.all.new_mypicklistvalue;
if( PL != null && PLV != null )
{
PL.style.display = "none";
PLV.style.display = "none";
// Create a DIV container
var addDiv = document.createElement("<div style='overflow-y:auto; height:80px; border:1px #6699cc solid; background-color:#ffffff;' />");
PL.parentNode.appendChild(addDiv);
// Initialize checkbox controls
for( var i = 1; i < PL.options.length; i++ )
{
var pOption = PL.options[i];
if( !IsChecked( pOption.text ) )
var addInput = document.createElement("<input type='checkbox' style='border:none; width:25px; align:left;' />" );
else
var addInput = document.createElement("<input type='checkbox' checked='checked' style='border:none; width:25px; align:left;' />" );
var addLabel = document.createElement( "<label />");
addLabel.innerText = pOption.text;
var addBr = document.createElement( "<br />");
PL.nextSibling.appendChild(addInput);
PL.nextSibling.appendChild(addLabel);
PL.nextSibling.appendChild(addBr);
}
// Check if it is selected
function IsChecked( pText )
{
if(PLV.value != "")
{
var PLVT = PLV.value.split("||");
for( var i = 0; i < PLVT.length; i++ )
{
if( PLVT[i] == pText )
return true;
}
}
return false;
}
// Save selected text
crmForm.attachEvent( "onsave" , OnSave);
function OnSave()
{
PLV.value = "";
var getInput = PL.nextSibling.getElementsByTagName("input");
for( var i = 0; i < getInput.length; i++ )
{
if( getInput[i].checked)
{
PLV.value += getInput[i].nextSibling.innerText + "||";
}
}
}
}
Now, we are going to insert this code in the Form OnLoad() event. In order to do this we select Settings > Customizations > Customize Entities and choose the entity where we want to put the multi-value Picklist.
We go to the entity form and click in Form Properties and Edit the Event OnLoad().

Verify the checkbox “The Event is Enabled” is checked.
The field that contains the values “new_mypicklistvalue”, must be in the page. We can hide its label but we cannot completely hide it, as it is going to take the script.
As loading the page takes some time, in order to load the jscript making the field containing the values not visible, what we can do is to put that field in another tab, for example in the tab Notes which is always present by default.

So this way it is not seen when the page is loading.
Regards!
Santiago Gonnet
More Posts