views:

1066

answers:

1

Hello - I am wondering if anyone has attempted the following or has an idea as to how to do it.

I have a WPFToolkit DataGrid which is bound to an ObservableCollection of items. As such, the DataGrid is shown with as many rows in the ObservableCollection, and as many columns as I have defined in for the DataGrid. That all is good. What I now need is to provide another view of the same data, only, instead, the DataGrid is shown with as many cells in the ObservableCollection.

So let's say, my ObservableCollection has 100 items in it. The original scenario showed the DataGrid with 100 rows and 1 column. In the modified scenario, I need to show it with 10 rows and 10 columns, where each cell shows the value that was in the original representation. In other words, I need to transform my 1D ObservableCollection to a 2D ObservableCollection and display it in the DataGrid. I know how to do that programmatically in the code behind, but can it be done in XAML?

Let me simplify the problem a little, in case anybody can have a crack at this. The XAML below does the following:

* Defines an XmlDataProvider just for dummy data
* Creates a DataGrid with 10 columns
      o each column is a DataGridTemplateColumn using the same CellTemplate
* The CellTemplate is a simple TextBlock bound to an XML element

If you run the XAML below, you will find that the DataGrid ends up with 5 rows, one for each book, and 10 columns that have identical content (all showing the book titles). However, what I am trying to accomplish, albeit with a different data set, is that in this case, I would end up with one row, with each book title appearing in a single cell in row 1, occupying cells 0-4, and nothing in cells 5-9. Then, if I added more data and had 12 books in my XML data source, I would get row 1 completely filled (cells covering the first 10 titles) and row 2 would get the first 2 cells filled.

Can my scenario be accomplished primarily in XAML, or should I resign myself to working in the code behind?

Any guidance would greatly be appreciated. Thanks so much!

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:custom="http://schemas.microsoft.com/wpf/2008/toolkit"
mc:Ignorable="d"
x:Name="UserControl"
d:DesignWidth="600" d:DesignHeight="400"  >
<UserControl.Resources>
    <XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">
        <x:XData>
            <Inventory xmlns="">
                <Books>
                    <Book ISBN="0-7356-0562-9" Stock="in" Number="9">
                        <Title>XML in Action</Title>
                        <Summary>XML Web Technology</Summary>
                    </Book>
                    <Book ISBN="0-7356-1370-2" Stock="in" Number="8">
                        <Title>Programming Microsoft Windows With C#</Title>
                        <Summary>C# Programming using the .NET Framework</Summary>
                    </Book>
                    <Book ISBN="0-7356-1288-9" Stock="out" Number="7">
                        <Title>Inside C#</Title>
                        <Summary>C# Language Programming</Summary>
                    </Book>
                    <Book ISBN="0-7356-1377-X" Stock="in" Number="5">
                        <Title>Introducing Microsoft .NET</Title>
                        <Summary>Overview of .NET Technology</Summary>
                    </Book>
                    <Book ISBN="0-7356-1448-2" Stock="out" Number="4">
                        <Title>Microsoft C# Language Specifications</Title>
                        <Summary>The C# language definition</Summary>
                    </Book>
                </Books>
                <CDs>
                    <CD Stock="in" Number="3">
                        <Title>Classical Collection</Title>
                        <Summary>Classical Music</Summary>
                    </CD>
                    <CD Stock="out" Number="9">
                        <Title>Jazz Collection</Title>
                        <Summary>Jazz Music</Summary>
                    </CD>
                </CDs>
            </Inventory>
        </x:XData>
    </XmlDataProvider>

    <DataTemplate x:Key="GridCellTemplate">
        <TextBlock>
            <TextBlock.Text>
                <Binding XPath="Title"/>
            </TextBlock.Text>
        </TextBlock>
    </DataTemplate>

</UserControl.Resources>

<Grid x:Name="LayoutRoot">
    <custom:DataGrid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" IsSynchronizedWithCurrentItem="True"
    Background="{DynamicResource WindowBackgroundBrush}" HeadersVisibility="All" RowDetailsVisibilityMode="Collapsed"
    SelectionUnit="CellOrRowHeader" CanUserResizeRows="False" GridLinesVisibility="None" RowHeaderWidth="35" AutoGenerateColumns="False"
    CanUserReorderColumns="False" CanUserSortColumns="False">
        <custom:DataGrid.Columns>
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="01" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="02" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="03" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="04" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="05" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="06" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="07" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="08" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="09" />
            <custom:DataGridTemplateColumn CellTemplate="{StaticResource GridCellTemplate}" Header="10" />
        </custom:DataGrid.Columns>
        <custom:DataGrid.ItemsSource>
            <Binding Source="{StaticResource InventoryData}" XPath="Book"/>
        </custom:DataGrid.ItemsSource>
    </custom:DataGrid>
</Grid>

+2  A: 

So, to rephrase your question simply, you have a collection of objects and you want to display them horizontally with 10 to a row. If there are more than 10, the extra items wrap around (reflow) to the next row.

Here's how you can do it extremely easily:

Don't use DataGrid. That's basically only for displaying objects 1 object to a row where columns show various pieces of data for that object.

Instead, use ListBox or ListView, and give it a new ItemsPanel, like so (use data templates to display complex objects):

<ListBox ItemsSource="{Binding SomeCollectionOfObjects}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="10"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

This will replace the default VirtualizingStackPanel used by ListBox to arrange its items with UniformGrid. The reason for using UniformGrid is because you can specify the number of Columns and/or Rows the grid should have. The panel will equally divide the display area among the ListBox's items, but with 10 columns (as you want).

If you don't want a fixed number of columns/rows, you could instead use a WrapPanel which would fit as many objects into a single row as possible and wrap to the next row, a bit like inline-block elements in html, or left-justified text.

One last thing: remember that each of these 3 panels I just mentioned can have their Orientation set to either Horizontal (default for UniformGrid and WrapPanel) or Vertical (default for VirtualizingStackPanel and StackPanel).

Furthermore, you could write your own panels for custom item layout (e.g. arranging items in a circle).

Benny Jobigan