2012-12-11 20 views
6

Ho una collezione che desidero associare a una griglia WPF.griglia wpf con colonne dinamiche

Il problema che sto affrontando è che il numero di colonne è dinamico e dipende da una collezione. Ecco un semplice mock up:

public interface IRows 
{ 
    string Message{get;} 
    IColumns[] Columns{get;} 
} 

public interface IColumns 
{ 
    string Header {get;} 
    AcknowledgementState AcknowledgementState{get;} 
} 

public interface IViewModel 
{ 
    ObservableCollection<IRows> Rows {get;} 
} 

Voglio che la mia vista di legarsi alla raccolta Righe, che contiene una raccolta di colonne.

La collezione My Columns contiene un enum che dovrebbe essere rappresentato da un'immagine (1 di 3 possibilità). Contiene anche una proprietà Message che deve essere visualizzata solo in una colonna (statica e solo alcune informazioni di testo). Contiene anche una stringa di intestazione che dovrebbe essere visualizzata come intestazione per quella colonna.

The link to what I want to show

noti che il numero di colonne è variabile (al momento le intestazioni sono impostati a riconoscere ma questo cambierà per rappresentare i dati dinamici).

Update: Questo è dopo l'implementazione di suggerimenti da Rachel

<ItemsControl 
ItemsSource="{Binding Items, Converter={StaticResource PresentationConverter}}"> 
    <ItemsControl.ItemsPanel> 
    <ItemsPanelTemplate> 
     <Grid ShowGridLines="true" 
     local:GridHelpers.RowCount="{Binding RowCount}" 
     local:GridHelpers.ColumnCount="{Binding ColumnCount}" /> 
    </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemContainerStyle> 
    <Style> 
     <Setter Property="Grid.Row" Value="{Binding RowIndex}"/> 
     <Setter Property="Grid.Column" Value="{Binding ColumnIndex}"/> 
    </Style> 
    </ItemsControl.ItemContainerStyle> 
    <ItemsControl.ItemTemplate> 
    <DataTemplate> 
     <ContentControl Content="{Binding}"> 
     <ContentControl.Resources> 
      <DataTemplate DataType="{x:Type UI:MessageEntity}"> 
      <TextBox Text="{Binding Message}"></TextBox> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type UI:StateEntity}"> 
      <TextBox Text="{Binding State}"></TextBox> 
      </DataTemplate> 
     </ContentControl.Resources> 
     </ContentControl> 
    </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Questo quasi mi dà quello che voglio ora. Sono solo bloccato con quello che dovrei fare per le intestazioni. Qualsiasi suggerimento è benvenuto.

+0

Per richiedere il supporto, dare il massimo delle informazioni. Include il collegamento ... – Harry

+0

semplificato e aggiunto un collegamento. – zman

+0

Link su come aggiungere righe e colonne in modo dinamico - http://stackoverflow.com/questions/13344788/how-to-create-listview-to-a-grid-programmatically/ – Sai

risposta

5

È possibile utilizzare annidato ItemsControls per questo

Ecco un esempio di base:

<!-- Bind Rows using the default StackPanel for the ItemsPanel --> 
<ItemsControl ItemsSource="{Binding Rows}"> 
    <!-- Set the Template for each row to a TextBlock and another ItemsControl --> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <StackPanel Orientation="Horizontal"> 
       <!-- Need to set Width of name TextBlock so items line up correctly --> 
       <TextBlock Width="200" Text="{Binding Name}" /> 

       <ItemsControl ItemsSource="{Binding Columns}"> 
        <!-- Use a horizontal StackPanel to display columns --> 
        <ItemsControl.ItemsPanel> 
         <ItemsPanelTemplate> 
          <StackPanel Orientation="Horizontal" /> 
         </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
       </ItemsControl> 
      </StackPanel> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 
+0

Questo è quasi quello che voglio. Ho provato a implementare una soluzione usando questa idea, ma ho trovato dei problemi quando ho aggiunto una riga di intestazione che ho reso indipendente da ItemsControl (solo un pannello di stack sopra di esso). È abbastanza complicato disporre le larghezze delle colonne in modo che si sincronizzino. – zman

+1

@ManuelZanin È possibile utilizzare una griglia con una proprietà associata [SharedSizeScope] (http://msdn.microsoft.com/en-us/library/system.windows.controls.grid.issharedsizescope.aspx), tuttavia è necessario definire le definizioni delle colonne in anticipo. Se il numero di colonne può cambiare, ho alcune proprietà allegate per la griglia [sul mio blog] (http://rachel53461.wordpress.com/2011/09/17/wpf-grids-rowcolumn-count-properties/) che ti consente di associare il conteggio delle colonne invece di specificare manualmente ColumnDefinitions. – Rachel

+0

Ok, ho quasi funzionato grazie ai tuoi suggerimenti. Ho aggiornato la mia domanda. L'unico problema rimasto è come trattare bene le intestazioni. Se non riesco a farlo funzionare utilizzando ItemsControl, potrei dover usare un ListView (anche se non ho molta familiarità con questo controllo). – zman

2

L'utilizzo di un approccio a griglia potrebbe rendere le cose più complicate di quanto dovrebbero. Hai provato a cambiare il template di un listview, o usare il DataGrid invece per questo scopo?

Per un esempio, dare un'occhiata a questo progetto: http://www.codeproject.com/Articles/25058/ListView-Layout-Manager

o questa: http://www.codeproject.com/Articles/16009/A-Much-Easier-to-Use-ListView

Se si va con la griglia, credo che si dovrà aggiungere un sacco di codice dietro a gestire la quantità di colonne e righe, le loro dimensioni, il contenuto della cella ... Mentre un ListView/DataGrid ti permetterà di farlo dinamicamente attraverso i Templates.

+0

Questi collegamenti non hanno a che fare con una collezione di colonne che ho visto. – Paparazzi

+0

@Blam E non si occupano nemmeno di una griglia! Qual è esattamente il mio punto: un DataTemplate all'interno di un ListView potrebbe essere una soluzione più adatta per lo scenario dell'OP. Quando ho avviato WPF, una volta ho iniziato a codificare una classe che generava una griglia con una quantità sconosciuta di colonne + intestazioni e alla fine ho imparato a conoscere ListView e come semplifica questo tipo di problema, soprattutto perché l'OP vuole che sia puro Soluzione XAML. – Joe

+0

Hai ragione, forse sto rendendo la vita troppo difficile per me stesso. Ho pensato di utilizzare un ListView/GridView ma non ho trovato alcun esempio di utilizzo per ottenere ciò che voglio (sono abbastanza arrugginito su WPF che non aiuta). Gli esempi che hai postato sono utili ma penso che sia eccessivo per il mio scopo. – zman

0

C'è anche la possibilità di utilizzare un oggetto dinamico per creare le colonne. Questo è un po 'laborioso, ma i risultati sono molto efficaci e la soluzione in generale è abbastanza flessibile.

Questo ti mostrerà le basi per l'oggetto dinamico Binding DynamicObject to a DataGrid with automatic column generation?

Ho avuto qualche problema di utilizzarlo con oggetti nidificati, le colonne che hanno gli oggetti e poi cercando di legare il contenuto cella per l'oggetto.

Ecco una domanda ho sollevato con un esempio di come fare questo

Problems binding to a the content of a WPF DataGridCell in XAML

Problemi correlati