Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
534 views
in Technique[技术] by (71.8m points)

mvvm - wpf grid with dynamic columns

I have a collection that I wish to bind to a WPF grid.

The problem I'm facing is that the number of columns is dynamic and is dependent on a collection. Here is a simple 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;}
}

I want my view to bind to the the Rows collection, which contains a collection of Columns.

My Columns collection contains an enum which should be represented by an image (1 of 3 possibilities). It also contains a Message property which should only be displayed in one column (static and is just some text information). It also contains a Header string which should be displayed as a header for that column.

The link to what I want to show

Note that the number of columns is variable (at the moment the headers are set to Acknowledge but this will change to represent dynamic data).

Update: This is after implementing suggestions from 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>

This almost gives me what I want now. I'm only stuck with what I should do for the headers. Any suggestions are welcome.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use nested ItemsControls for this

Here's a basic example:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...