wpf display staggered content
- by Chris Cap
I am trying to display a rather dynamic list of data in WPF. I have essentially a LineItem class that contains a list of strings and a line type. The line type separates different categories of line items. All line items with the same type should be displayed the same and their data should line up. For example, this list will contain an order summary. And the there will be a line type that represents something with a width and height. The width and height must line up vertically. However, there may be other line types that don't have to line up vertically. I want to produce a table similar to what you see below:
------------------------------------------------------------------
| some content here | some more content here | last content here |
|----------------------------------------------------------------|
| some content here | | last content here |
|----------------------------------------------------------------|
| spanning content that is longer then most | last content here |
|----------------------------------------------------------------|
| some content that can span a really long distance |
------------------------------------------------------------------
I attempted to do this by creating ListView with a single column that had a datatemplate that contained a grid with a fixed number of fields and then bind to the Colspan value. Unfortunately, this didn't work. I ended up with incorrect or overlapping content anytime I tried to do a column span. Here's the XAML I was working with
<ListView ItemsSource="{Binding}" >
<ListView.View>
<GridView>
<GridViewColumn Header="Content">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Grid.ColumnSpan="{Binding Path=Tokens[0].ColumnSpan}" Text="{Binding Path=Tokens[0].Content}" ></TextBlock>
<TextBlock Grid.Column="1" Grid.ColumnSpan="{Binding Path=Tokens[1].ColumnSpan}" Text="{Binding Path=Tokens[1].Content}" ></TextBlock>
<TextBlock Grid.Column="2" Text="{Binding Path=Tokens[2].Content}"></TextBlock>
</Grid>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
And here's the classes I was binding to
public class DisplayLine
{
public LineType Linetype { get; set; }
public List<Token> Tokens { get; set; }
public DisplayLine()
{
Tokens = new List<Token>();
}
}
public class Token
{
public string Content { get; set; }
public bool IsEmpty { get { return string.IsNullOrEmpty(Content); } }
public int ColumnSpan { get; set; }
public Token()
{
ColumnSpan = 1;
}
}
Does anyone have any suggestions of maybe a way of making this work. I may be taking the wrong approach. I'm trying to avoid any solutions where I explcitily build something in the code behind as I'm using the MVVM pattern so it has to be something that I can bind from exposed through the controller. My intial plan was to create a factory and separate classes that display the data differently based on type. However, I'm struggling coming up with a strategy for this using MVVM as I really can't just build something and display it. I have toyed with the idea of making some kind of UI service class that is injected, but it would still require some pretty detailed UI information from the controller to do it's work.