2010-11-22 66 views
4

I ont une table Item qui se compose de 3 colonnes:WPF DataGrid bidimensionnel/ListView?

ItemId int PK 
RoomId int FK 
UnitId int FK 
Cost money 

Je veux avoir une grille de données/ListView ayant des colonnes et des rangées représentant le pivot suivant générées dynamiquement:

 Room1 Room2 Room3 Room4 
Unit1 $34 $72 $48 $98 
Unit2 $64 $56 $67 $24 
Unit3 $24 $34 $34 $34 

Je préfère un contrôle ou un assistant à un existant plutôt que d'une fonction sale puisque je vais avoir besoin de ce scénario beaucoup, mais tout est chaudement accueilli.

Je souhaite avoir les Room1 et les Unit1 etc. comme en-têtes de ligne et de colonne, et les cellules générées/définies en conséquence.

Répondre

8

Tout d'abord, vous aurez besoin de convertir votre collection de Item objets dans une collection appropriée:

var dict = data.Select(i => i.UnitId).Distinct() 
    .ToDictionary(u => u, u => data 
     .Where(i => i.UnitId == u) 
     .ToDictionary(d => d.RoomId, d => d)); 
var rooms = dict.Values.First().Keys; 
DataContext = Tuple.Create(dict, rooms); 

et vous avez besoin d'un ItemsControl avec la configuration correcte DataTemplate

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="Auto" /> 
    <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <ItemsControl ItemsSource="{Binding Item2}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
     <StackPanel Orientation="Horizontal" 
        Margin="80,0,0,0" /> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
     <TextBlock HorizontalAlignment="Center" 
        Foreground="Blue" 
        Width="80" 
        Margin="5"> 
         <Run Text="Room" /> 
         <Run Text="{Binding Mode=OneWay}" /> 
     </TextBlock> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    </ItemsControl> 
    <ItemsControl ItemsSource="{Binding Item1}" 
       AlternationCount="{Binding Count}" 
       Grid.Row="1"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
     <StackPanel Orientation="Horizontal"> 
      <TextBlock VerticalAlignment="Center" 
        Foreground="Blue" 
        Width="80"> 
         <Run Text="Unit" /> 
         <Run Text="{Binding Key, Mode=OneWay}" /> 
      </TextBlock> 
      <ItemsControl ItemsSource="{Binding Value}" 
         VerticalAlignment="Center"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
       <TextBlock Text="{Binding Path=Value.Cost, StringFormat={}{0:C}}" 
          Margin="5" 
          Width="80" /> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
      </ItemsControl> 
     </StackPanel> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Grid> 

et vous obtenir ceci:

alt text

+0

génial! impressionnant! Pensez-vous d'une façon que je serai capable d'utiliser DataGridColumnHeader et DataGridRowHeader pour les en-têtes? Je pense que je suis à la recherche d'un contrôle personnalisé qui hérite de Selector ou MultiSelector qui devrait avoir un ColumnItemsSource, RowItemsSource et un événement GeneratingCell que son EventArgs fournit à la cellule actuelle Item + Unit, et une propriété que je dois fournir à DataContext de la cellule génératrice, il génère la cellule par rapport à la propriété CellDataTemplate. mais comme je n'ai aucune expérience sérieuse dans le développement de contrôles personnalisés, il m'est très difficile de recommencer à zéro. – Shimmy

+0

Surtout lorsque l'élément de données de la cellule est inconnu et est fourni par l'utilisateur à la demande. En attendant, je vais utiliser votre solution, j'espère que vous aurez du temps pour poster un contrôle personnalisé. toute la communauté te le doit. un tel contrôle est très essentiel. – Shimmy

+0

superbe, merci. – Ric