In an application I was working on recently, I needed to implement a split screen, like those on the closed-circuit cameras monitors. Usually, a simple Grid or a UniformGrid would do the trick, but in this case, the requirement was to allow the user to dynamically change the grid’s structure. The following screenshots shows the grid’s structure when the user chooses to display two, three, or four screens, respectively:
As you can see, different user selections requires entirely different grid structure, with different number of rows and columns and even different spans for some of the grid’s children. After giving the problem some thought, I came up with a solution that enabled me to do just that, and which can be easily extended in the future to include additional structures.
DynamicGridFormationBehavior is a behavior that can be applied to a grid to allow changing its structure to one of several predefined formations, based on the desired number of visible children. The behavior contains the following dependency properties:
The NumberOfVisibleChildren property contains the desired number of the grid’s children to display. Based on this value, a predefined formation will be chosen.
The Formations property contains the predefined formations, as defined in the xaml file. Each formation is of type DynamicGridFormation.
Each formation contains the following properties:
- NumberOfChildren – The number of visible children, for which the formation should be used.
- NumberOfRows – The number of rows that the grid will contain when this formation is used.
- NumberOfColumns – The number of columns that the grid will contain when this formation is used.
- ChildProperties – A collection of DynamicGridChildProperties elements.
The DynamicGridChildProperties class contains grid-related properties for each child that will be shown in the formation. When the formation is applied, each visible child will be placed within the grid based on the following properties:
- Index – The index in the grid’s Children collection, which contains the child onto which these properties should be applied.
- Row – The grid’s row in which the child should be placed.
- Column – The grid’s column in which the child should be placed.
- RowSpan – The number of rows that the child will span within the grid.
- ColumnSpan – The number of columns that the child will span within the grid.
- Visibility – The visibility of the child.
Notice that both the DynamicGridFormation class and the DynamicGridChildProperties class inherits from the Freezable class. It is needed to support DataContext inheritance.
The following markup shows how to use the behavior:
Four formations are defined to represent the states shown in the screenshots above. Also, notice how the NumberOfVisibleChildren property is bound to the value of the view model’s NumberOfVisibleItems property, allowing a clear separation between the logic that determines how many children to show, and the way in which they are shown.
The code is available on GitHub, as part of my WPFUtils project.