wpf-Gitter mit dynamischen Spalten




mvvm grid (3)

Ich habe eine Sammlung, die ich an ein WPF-Gitter binden möchte.

Das Problem, dem ich gegenüberstehe, ist, dass die Anzahl der Spalten dynamisch ist und von einer Sammlung abhängt. Hier ist ein einfaches 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;}
}

Ich möchte, dass meine Ansicht an die Sammlung "Zeilen" gebunden wird, die eine Sammlung von Spalten enthält.

Meine Columns-Sammlung enthält eine Enum, die durch ein Bild repräsentiert werden sollte (1 von 3 Möglichkeiten). Es enthält auch eine Message-Eigenschaft, die nur in einer Spalte angezeigt werden sollte (statisch und nur einige Textinformationen). Es enthält auch eine Header-Zeichenfolge, die als Überschrift für diese Spalte angezeigt werden soll.

Beachten Sie, dass die Anzahl der Spalten variabel ist (in dem Moment, in dem die Header auf Acknowledge gesetzt sind, aber dies ändert sich, um dynamische Daten darzustellen).

Update: Dies ist nach der Umsetzung von Vorschlägen von 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>

Das gibt mir fast das, was ich jetzt will. Ich bleibe nur bei dem, was ich für die Header tun sollte. Irgendwelche Vorschläge sind willkommen.


Die Verwendung eines Grid-Ansatzes könnte die Dinge komplizierter machen, als sie sein sollten. Haben Sie versucht, die Vorlage einer Listview zu ändern oder stattdessen das DataGrid zu diesem Zweck zu verwenden?

Schauen Sie sich beispielsweise dieses Projekt an: http://www.codeproject.com/Articles/25058/ListView-Layout-Manager

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

Wenn Sie mit dem Grid gehen, glaube ich, dass Sie viel Code hinzufügen müssen, um die Anzahl der Spalten und Zeilen, ihre Größe, den Zelleninhalt zu verwalten ... Während ein ListView / DataGrid dies dynamisch durchlässt Vorlagen.


Sie können dafür verschachtelte ItemsControls

Hier ist ein einfaches Beispiel:

<!-- 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>

Sie können auch ein dynamisches Objekt zum Erstellen Ihrer Spalten verwenden. Dies ist ein wenig mühsam, aber die Ergebnisse sind sehr effektiv und die Lösung im Allgemeinen ist sehr flexibel.

Dies zeigt Ihnen die Grundlagen für das dynamische Objekt Binding DynamicObject zu einem DataGrid mit automatischer Spaltengenerierung?

Ich hatte einige Probleme damit, verschachtelte Objekte zu verwenden, Spalten, die Objekte enthalten und dann versuchen, Zellinhalte an das Objekt zu binden.

Hier ist eine Frage, die ich mit einem Beispiel für die Vorgehensweise aufgeworfen habe

Probleme beim Binden an den Inhalt einer WPF DataGridCell in XAML





multiple-columns