Search code examples
c#wpflistviewwpfdatagrid

Merge columns if a property is empty


I have a class with some string properties and each class is displayed as a row in a data grid. Each property has a column of its own. If two adjacent properties are empty, I would like to merge those two columns for that particular row. I am open to using a datagrid or a listview as long as it does the job. E.g.

public class MyClass
{
    string name { get; set;}
    string age { get; set;}
    string sex { get; set;}
    double income { get; set;}
}

Merged Column


Solution

  • You better use an ItemsControl for these kinds of situations. My suggestion is to use a Grid as ItemsPanel and instead of say 100 instances of MyClass, implement a Cell class and use 400 of them (each for one cell) and set their exact row and column in code.

    You will need a GridHelper which you can find it in this link

    public class Cell
    {
        public int RowIndex { get; set; }
        public int ColumnIndex { get; set; }
        public int ColumnSpan { get; set; }
        public string Data { get; set; }
        public CellType CellType { get; set; } //you can also add an enum for CellType
    }
    
    <ItemsControl ItemsSource="{Binding AllCells}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid 
                    v:GridHelper.ColumnsCount="{Binding TotalColumns}"
                    v:GridHelper.RowsCount="{Binding TotalRows}">
                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemContainerStyle>
            <Style TargetType="ContentPresenter">
                <Setter Property="Grid.Row" Value="{Binding Path=RowIndex}"/>
                <Setter Property="Grid.Column" Value="{Binding Path=ColumnIndex}"/>
                <Setter Property="Grid.ColumnSpan" Value="{Binding Path=ColumnSpan}"/>
            </Style>
        </ItemsControl.ItemContainerStyle>
    </ItemsControl>
    

    If you need different types of cells, you can add this to the ItemContainerStyle:

    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=CellType}" Value="NumericCellType">
            <Setter Property="ContentTemplate" Value="{StaticResource templateNumericCell}"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=CellType}" Value="GeneralCellType">
            <Setter Property="ContentTemplate" Value="{StaticResource templateGeneralCell}"/>
        </DataTrigger>
    </Style.Triggers>
    

    Or else you can implement a single template:

    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Data}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>