I’ve had an active interest in XrmToolbox plugins for a while now, as evidenced by my recent posts. It’s a powerful toolkit for developers and admins and a great way for those unfamiliar to learn a bit about the platform. I use the XrmToolbox regularly on multiple projects, I’ve dug into the code for several plugins, and I’ve built a few of my own plugins. As a developer, I can build a plugin that solves a particular problem my team might encounter and I have an audience with which I can share plugins and code. This community feedback ultimately improves my plugin contribution and my knowledge of the platform!
Starting a new plugin is fairly straightforward, especially with the latest Visual Studio template provided by Tanguy Touzard, the XrmToolbox head honcho. Check out his latest documentation and download Visual Studio 2017 templates here: Create your own plugin for XrmToolBox. With the template, you get a base plugin class, a base plugin control, examples on handling async events, service connections, etc. Overall, it’s really cool stuff and in a very short time, your own plugin is up and running.
Sharing code and functionality
I have created two plugins and have some ideas for others on which I am actively working. While using other developer’s plugins, I often see similarities on general design and user interface elements. Plugins might want to query a list of records, retrieve a list of Entity metadata, or present some text editing capabilities for CRM resources. Like most developers, I do my best to avoid duplicate code within a project, between projects in the same solution, and across multiple solutions. That’s why we see lots of helper classes, shared assemblies, or third party components in our projects: build things once and leverage them across solutions. You can save time with new development and fixing issues, while providing common patterns for both developers and end users.
So why not do the same with XrmToolbox user interface components?
One common element that I see in XrmToolbox plugins dealing with the metadata services is rendering a list of Entities for the user. For example, in my Typescript Helper Class Utility plugin, the primary user control is a list of Entities with a few columns showing EntityMetadata details. From this list, you check Entities for which you would like to generate the Typescript templates. Reviewing other XrmToolbox plugins, I quickly found similar user interface models, such as with the View Transfer Tool and View Layout Replicator. These two plugins have an almost identical ListView providing a list of Entities for the user to select. Once an Entity is selected, the right hand pane loads a list of Views for the selected Entity.
This is a perfect example of where a shared user interface component would be very useful. Rather than duplicating the code for each project, we could encapsulate this functionality into a reusable user control.
Shared Entity List View
With my Typescript Helper Class Utility, I already wrote some code which loads Entities for the connection into a ListView, similar to the View Transfer and Layout Replicator plugins above. In fact, I leveraged some of the code provided by Tanguy to sort my ListView properly. With this code, I provide some additional toolbar items filtering, sorting, and checking list items. So as a first attempt at shared user interface components for the XrmToolbox, I decided to package this functionality into a self contained user control that can be referenced in another XrmToolbox project.
Building reusable components is a great idea, but I had to immediately step back and think about what would be useful to myself and other developers with this control. Based on what I already built with my plugin, I decided on the following primary features:
- Provide a self contained user control that loads a list of Entities for the parent plugin connection
- Allow sorting and filtering the Entities list
- Allow multiple selection of Entities
- Expose the currently selected and list of check Entities to the parent plugin
- Expose the list of all loaded Entities to the parent plugin
- Expose some common events to the parent plugin
I created a new XrmToolbox plugin project and pulled in the pieces required by the Entities List View functionality. Starting with the XrmToolbox plugin template made things easy with the included references and Nuget packages. The user interface elements in my new user control consisted of the ListView control, the toolbar and Entities List related command buttons, the code behind that loads the Entities, and some additional helper classes. I created an additional XrmToolbox project as a test bed that allows testing the exposed events, lists of objects, and general functionality of the Entities List View control.
Within my test container plugin, you can see the the ListView of Entities that looks much the same as the Typescript Helper Class Utility plugin. In the middle panel, I bound the selected Entity in the list to the Property Grid control so you can view the selected Entity details. The exposed object is the full EntityMetadata object retrieved with the SDK metadata call. I had considered exposing only an EntityReference but decided on the EntityMetadata for the first iteration. In the far right panel, I am logging the events that have been exposed on the control where you can see initialization and all of the selection change events.
Overall, this seems to be working fairly well with my first bit of testing. I need to complete more thorough testing around making service calls and leveraging the parent plugin control WorkAsync objects. I am also completing wiring up the events and additional methods and properties for the parent plugin control. For example, I would like to allow configuring which properties are displayed as columns in the grid and additional action methods such as pre-filtering the list on load.
I will follow up with another post once I complete these tasks with some additional details. I am going to also post the code and documentation on the control interface on Github for everyone to review and hopefully use in their own projects. Longer term, I plan on building a few other reusable controls for XrmToolbox plugin developers.
In the meantime, I would really like to hear what features would be useful for the initial and following releases. I developed this control based on my usage of the XrmToolbox and experience developing plugins, so I definitely appreciate hearing what might be useful for other developers.