2010-11-22 3 views
4

Ich habe eine Tabelle Item, die aus 3 Spalten besteht:WPF zweidimensionales DataGrid/ListView?

ItemId int PK 
RoomId int FK 
UnitId int FK 
Cost money 

Ich möchte dynamisch generierten Spalten und Zeilen der folgende Dreh mit einem Datenraster/Listview haben darstellen:

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

I a bevorzugen Kontrolle oder ein Helfer zu einer vorhandenen eher als eine schmutzige Funktion, da ich dieses Szenario sehr brauche, aber alles überhaupt herzlich willkommen ist.

Ich möchte die Room1 und die Unit1 usw. als Zeilen- und Spaltenüberschriften haben, und die Zellen generiert/entsprechend eingestellt.

Antwort

8

Erstens müssen Sie Ihre Sammlung von Item Objekten in eine geeignete Sammlung konvertieren:

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); 

und dann benötigen Sie ein ItemsControl mit der richtigen Konfiguration 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> 

und dann Sie Holen Sie sich dies:

alt text

+0

großartig! fantastisch! Denkst du darüber nach, wie ich DataGridColumnHeader und DataGridRowHeader für die Header verwenden kann? Ich glaube, ich suche nach einem benutzerdefinierten Steuerelement, das Selector oder MultiSelector erbt, das eine ColumnItemsSource, RowItemsSource und ein Ereignis GeneratingCell haben sollte, dass seine EventArgs die aktuelle Zelle Item + Unit bereitstellt, und eine Eigenschaft, die ich dem DataContext der generierenden Zelle bereitstellen muss. Es generiert die Zelle für die CellDataTemplate-Eigenschaft. Aber da ich keine ernsthaften Erfahrungen mit der Entwicklung von benutzerdefinierten Steuerelementen habe, fällt es mir sehr schwer, bei Null anzufangen. – Shimmy

+0

Insbesondere wenn das Zellendatenelement unbekannt ist und vom Benutzer bei Bedarf bereitgestellt wird. In der Zwischenzeit werde ich Ihre Lösung verwenden, ich hoffe, Sie werden etwas Zeit haben, um ein benutzerdefiniertes Steuerelement zu veröffentlichen. die ganze Gemeinschaft wird dir dafür danken. Eine solche Kontrolle ist sehr wichtig. – Shimmy

+0

super, danke. – Ric