Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: How to create a custom items control panel?

I want to design a custom items control panel for a ListBox. There are 3 requirements:

  1. It should have the properties int rows and int columns which would define the matrix of cells that the panel is made of. This is what the panel should look like (colors are irrelevant, I just wanted to show that the panel is consisted of 12 empty cells in a 3x4 matrix): alt text

  2. If the number of items in the items control is less than the number of defined cells all the cells should be drawn. E.g. if there are only 4 items to be placed in a 3x4 matrix shown in the picture, all of the cells should be drawn and only 4 of them should contain the items.

  3. It should be possible to set which cell will host which item, via some data binding. For example, let's say I had a list of persons. That list contains items of type Person and the Person class contains two properties X and Y. I should be able to data bind X to the row of the cell and Y to the column of the cell, thus allowing myself to set which cell in the panel will contain which person from the list.

If creating the items control panel doesn't make sense, please recommend what would be the better approach. To be quite honest I am puzzled on how to even get started with this. Thanks for all the help. Cheers!

like image 514
Boris Avatar asked Nov 14 '22 04:11

Boris


1 Answers

A useful strategy to solve this kind of problem is to manipulate the source data into a format more suitable for consumption by an ItemsControl. For example, a two-dimensional array of items, or a linear collection of items that contain their own two-dimensional coordinates, is hard to utilize.

Instead, with a simple data structure transformation you can bind your ItemsSource to collection of collections. The outer collection contains three rows and each inner collection contains four items. Each item can contain its actual row and column coordinates and can handle whether the corresponding cell should display any data.

Here's a 2x2 example to show you what I mean:

<Grid>
    <Grid.Resources>
        <coll:ArrayList x:Key="sampleData">
            <x:Array Type="sys:String">
                <sys:String>1</sys:String><sys:String>2</sys:String>
            </x:Array>
            <x:Array Type="sys:String">
                <sys:String>3</sys:String<sys:String>4</sys:String>
            </x:Array>
        </coll:ArrayList>
    </Grid.Resources>
    <ItemsControl ItemsSource="{StaticResource sampleData}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Border BorderBrush="Black" BorderThickness="1" Width="50" Height="50">
                                <TextBlock Text="{Binding}"/>
                            </Border>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

which produces:

+---+---+
| 1 | 2 |
+---+---+
| 3 | 4 |
+---+---+
like image 192
Rick Sladkey Avatar answered Dec 11 '22 08:12

Rick Sladkey