This month I am pleased to introduce Jeremy Hofmann, a Manager in Crowe Horwath's Dynamics CRM practice and is responsible for many successful deployments of Dynamics CRM across North America. In his usual style Jeremy steps out of the box and shows how Microsoft Windows Presentation Foundation can be leveraged in Microsoft Dynamics CRM 4.0.
Microsoft CRM 4.0 allows your organization to track accounts, contacts, leads, opportunities, activities, support cases, and a vast array of additional business information users need. In addition, you can leverage the platform to create your own related custom entities that model your business information and allow your users to manage day to day customer interactions.
From a user’s perspective, the power and flexibility to extend the system is incredible, but it has the potential to cause usability issues. How do busy users quickly and easily get access to the most relevant information? How can you provide a targeted, personalized user experience that presents CRM information and relationships directly to the user in time of need?
The answer is to customize the user experience by bringing together the most frequently used, and most relevant data all in one central location – to build a CRM “dashboard”. This is where the challenge presents itself – defining the information to be displayed, and determining how to build a fast and responsive solution to provide the best user experience possible.
In this article, I’ll show you how to build your own custom CRM dashboards, using Microsoft’s Windows Presentation Foundation to construct the user interface.
What You Will Need
You can design Windows Presentation Foundation (WPF) applications using Microsoft Visual Studio 2005 or 2008. I prefer to use VS 2008 since it’s the latest and greatest. Feel free to use the Visual Studio 2008 Express edition, as it is free to download and easy to install.
If you use Visual Studio 2005, you will need to download and install the Visual Studio 2005 Extensions for .NET 3.0.
Here’s a sample dashboard we’ll build together. This dashboard lists CRM accounts on the left side. When an account is selected on the left, the dashboard will display the related record information on the right. You can add, remove, or customize the panels as you see fit for your users. In a moment, you’ll see how easy it is to bind CRM data to a WPF template in order to display this information.
Let’s get started by creating a new Windows Presentation Foundation project in Visual Studio. Select the “WPF Application” template and give your project a name.
Visual Studio will load the template and present you with a brand new Window1.xaml file for you to work with. Add a web reference to the CRM web server. I called mine CRMService. If you need additional information on this topic, there is more information in the CRM 4.0 SDK on how to do this.
Hint: If you are using Visual Studio 2008, you may have a little trouble finding the “Add Web Reference” option. It’s still there – first use the “Add Service Reference” menu, and then click the Advanced button.
We’ll also need to reference the Microsoft CRM SDK .dlls, microsoft.crm.sdk.dll, and microsoft.crm.sdktypeproxy.dll, which can be found in the bin folder of the Microsoft CRM SDK. Go ahead and set a reference to those assemblies as well.
Actually, we’ll be referencing the CRM web service and the SDK assemblies quite a bit, so let’s set up a using statement to make things a little cleaner. Now we’re ready to go!
The Account List
The first thing we’ll do is create the account list on the left side. This will allow the user to select an account. In this section, we’ll connect to the CRM web server, query all accounts, and then create the WPF markup to display the accounts. Finally, we’ll show how to bind the accounts to the WPF control.
View the code behind the Window1.xaml, add a class level variable to reference the CRMService, and modify the default Window1 constructor to create a new instance of to the CRM service.
You may have to change the CRM service URL to point to your CRM server. If you’re using the Microsoft Virtual PC image, change it to http://localhost:5555/....
So far this is just standard CRM development. We’ve added a web reference to our CRM web service and we’ve created an instance of the class.
Now we need to connect to the CRM web service and retrieve the CRM accounts. We’ll retrieve the accounts as BusinessEntity objects so that we can bind to them using WPF. In the Window1 constructor, add the following code after the code to connect to the CRM web service.
Great! This by itself should compile and run. However, it does not yet do anything too spectacular. Next is the fun part – creating your own XAML markup to render the account list any way you’d like.
Switch over to the Window1.xaml designer. You should see the following design pane:
Notice here there are two main design panes. The top pane is a graphical preview of the changes you make in the markup section in the bottom pane. You can collapse either pane if you prefer to work in one or the other. I prefer to work in the text (bottom) pane since I like to torture myself…I mean, have total control…over the markup design. It’s also a great way to learn WPF markup if you are just getting started with it.
Notice also that there is a top-level Window element and a single Grid element within it. I won’t go into all the details here of the Window element, just know that it is the default element when creating WPF applications and that you can change some of the basics within it, such as the title bar text, height, and width of the window.
Now some background – WPF is a little like HTML. The idea is for you to markup the layout and presentation for what you’d like to show and the system will render this markup for you when the program runs. It’s also a bit like HTML in that you can put elements and controls inside of one another, and “build up” your user interface as a sort of tree.
One of the main elements in WPF is the Grid. You can think of a Grid almost like a table, with rows and columns. Within the Grid, you can pin down controls so that they are rendered at an exact row and column.
In our dashboard, we’ll want to have two main columns. The first column will contain our accounts list, and the second column will contain all of our panels and related information.
Within the Grid element, place the following markup.
The Width values tell WPF how wide to make each column. As a best practice, I like to make all of my column widths add up to 100. This allows you to treat each column width as a percentage, similar to HTML table design. In this example, the first column will take up 40% of the width, and the second column will take up the remaining 60%.
Another common layout element in WPF is the DockPanel. A DockPanel allows you to put other controls inside of it, and to “dock”, or fix, each control to either the top, bottom, left, or right side of the DockPanel. This allows for great flexibility and automatic stretching and resizing of the child controls.
Let’s throw down a new DockPanel in the first column of the Grid. Place the following markup in the Grid element, after the Grid.ColumnDefinitions element.
Back to the Accounts List
Now we can add our list view to display the list of accounts. Add the following markup within the DockPanel that we just created.
Some things to point out here – first, there’s another DockPanel with a TextBlock inside. This is just a section header label we’ll use so the user can identify the section.
Second, we’re using the ListView control. This is just a WPF control that works very similar to a .NET data grid. You define one or more columns and then bind those columns to a field in your data.
In this example, we are defining a GridViewColumn element within the GridView, and then we are setting the DisplayMemberBinding attribute to the “name” property from our data. This is all it takes to tell WPF which field from the CRM record you want to display in that column! Feel free to add additional columns from the CRM account record if you’d like.
Finally, we need to tell this ListView where to get its data from. Back in the code view, add a line of code immediately after retrieving the CRM accounts from the CRM web service.
// Bind the accounts to the WPF list view
lstMain.ItemsSource = accounts.BusinessEntities;
Now if you compile and run, your CRM accounts list should be populating with a list of accounts from your CRM system. Fantastic!
What kind of dashboard would we have if we didn’t display related information? In the following sections, we’ll add some additional panels to display the general information from the account, associated activities, and even mix in a CRM web page just for fun.
General Information Panel
In this panel, we’ll display a few of the account record details. Begin by adding the following markup to the designer, immediately after the first DockPanel that we added above.
This is just another DockPanel. This time we threw a StackPanel inside of it, placed a StackPanel inside of that, then added four TextBlock controls inside of that. The first StackPanel just anchors the following controls to the top of the DockPanel. The second StackPanel then tells WPF to render the following controls in order, top to bottom. The first TextBlock just displays some fixed text for the section header. Each TextBlock after that is bound to a specific field on the account record.
Don’t worry too much about the binding syntax for now – it looks a little funny at first but there are plenty of samples out there for you to reference. The key is to set the Path property to the attribute that you want to display.
The real magic comes when we bind the DockPanel to the account record. To do this, first we need to add an event handler to the account list, telling it to run some code whenever anyone clicks an account. Add a MouseUp property to the lstMain ListView control that we created earlier.
<ListView Name="lstMain" MouseUp="GridViewColumn_MouseUp" ...>
Now switch back to the code and add the following event handler code.
Now whenever someone clicks an account in the account list, the program will pull the account out of the list and bind the DockPanel to that account. It’s that easy.
Run the program again and select an account to make sure you’re on the right track.
In the next panel, we’ll display a list of the open and closed activities for the account. Add the following markup to the designer, immediately under the last StackPanel that we added for the “General Information” section, and within the DockPanel.
This is just like the ListView that we added to display the accounts. The only difference here is that we are displaying fields from the activity entity.
Back in the code behind, we’ll need to grab the activities for the selected account and bind the results to the ListView. Place this code in the GridViewColumn_MouseUp handler, immediately after the existing code.
Run the program again to make sure everything is coded properly. You now have a working WPF dashboard!
Embedding a Web Page
The final dashboard component we’ll add is an embedded web page to display the CRM activity. When the user clicks the activity in the activity list, the panel will display the actual CRM activity web page directly in the WPF application.
First, let’s add the event handler markup for the MouseUp event to the lstActivity ListView.
<ListView Name="lstActivity" MouseUp="lstActivity_MouseUp" ... >
Now add the markup to display the web page, immediately after the last StackPanel but still within the main DockPanel.
This works a bit like a CRM iFrame control. Our job is to set the Frame’s source property in the click event. Add the following in the code behind.
private void lstActivity_MouseUp(object sender, MouseButtonEventArgs e)
Now when a user clicks the activity, the Frame will switch to the CRM web page for that activity.
Give it a try.
Decorating the Panels
A WPF application wouldn’t be a WPF application unless you spiced up the style a bit. I this section, I’ll show you some tricks you can use to give the dashboard a little pizzazz.
Let’s add a rounded border to our panels. WPF makes this very easy if you use a Border element. You can decorate your DockPanels and StackPanels with a Border element, and set the CornerRadius and Margin properties so that they will render with a rounded table effect.
Add the following markup just inside the first DockPanel.
Notice the results. You can control the “roundness” of the border by adjusting the CornerRadius property. Also, play around with the BorderThickness property to increase or decrease the border’s width.
Repeat the Border markup inside of the General Information, Activities List, and Activity Frame panels. For the General Information and Activities list, you will want to place the border directly inside of the StackPanel element. For the Activity Frame, place it directly inside of the first DockPanel.
Finally, we’ll set the title property, startup size, and start up location of the Window element at the very top of the markup designer.
By now you’ve seen how to create a basic WPF application, how to add markup to display CRM information, and how to connect your application to your CRM data.
You could take this application and add additional panels, display geographic or map information, embed SQL Reporting Service reports, SharePoint parts, or any other data that your users would find relevant.
You could also extend the dashboard to allow your users to import and arrange custom panels that you publish to a central location. The sky’s the limit.
We’ve seen how CRM 4.0 can be combined with WPF to give your users a rich client experience, with relevant CRM information at their fingertips. All of this takes place inside of a rich client-side application that will provide your users with a speedy, interactive application that can be enhanced over time.
I encourage you to try building a dashboard of your own, and to learn more about the display capabilities of Windows Presentation Foundation. I think you’ll find it provides a powerful new interface for building rich client applications that will make your users more productive, well-organized, and happy.
Jeremy is a Manager within Crowe Horwath’s CRM practice and specializes in combining Microsoft CRM with related technologies. He lives in the Chicago area and can be contacted at firstname.lastname@example.org.