How can I get stacked plots on the panel in WPF?

317 views Asked by At

I was wondering if you could help me with something. I'm trying to get stacked plots like this picture.

Stacked plots

I'm using UniformGrid to try to get something like this, but it's not correct.

<UniformGrid x:Name="plots" Rows="2">
            <StackPanel x:Name="plot1" IsEnabled="False" Visibility="Collapsed">
                <Grid MinWidth="300" MinHeight="300">
                    <WpfPlot x:Name="hr_graph"/>
                </Grid>
            </StackPanel>
            <StackPanel x:Name="plot2" IsEnabled="False" Visibility="Collapsed">
                <Grid MinWidth="300" MinHeight="300" >
                    <WpfPlot x:Name="sat_graph"/>
                </Grid>
            </StackPanel>
            <StackPanel x:Name="plot3" IsEnabled="False" Visibility="Collapsed">
                <Grid MinWidth="300" MinHeight="300">
                    <WpfPlot x:Name="pul_graph"/>
                </Grid>
            </StackPanel>
            <StackPanel x:Name="plot4" IsEnabled="False" Visibility="Collapsed">
                <Grid MinWidth="300" MinHeight="300">
                    <WpfPlot x:Name="per_graph" />
                </Grid>
            </StackPanel>
        </UniformGrid>
1

There are 1 answers

3
Quercus On BEST ANSWER

You can make this container just a generic ItemsControl, and change its ItemsPanel according to number of visible panels.
For example:

<DataTemplate x:Name="PartsLayout">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Slider x:Name="Slider" Margin="6" Value="4" Minimum="1" Maximum="4" TickFrequency="1" IsSnapToTickEnabled="True" />
            <TextBlock Grid.Column="1" Margin="6" Text="{Binding Value, ElementName=Slider}" />
        </Grid>
        <ItemsControl x:Name="Items" Grid.Row="1">
            <StackPanel x:Name="Part1" Background="Yellow" Grid.Row="0" Grid.Column="0" />
            <StackPanel x:Name="Part2" Background="Green" Grid.Row="0" Grid.Column="1" />
            <StackPanel x:Name="Part3" Background="Red" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" />
            <StackPanel x:Name="Part4" Background="Blue" Grid.Row="1" Grid.Column="1" />
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <UniformGrid Rows="2" Columns="2" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Value, ElementName=Slider}" Value="3">
            <Setter TargetName="Part4" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="Items" Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                        </Grid>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Value, ElementName=Slider}" Value="2">
            <Setter TargetName="Part4" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="Part3" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="Items" Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <UniformGrid Rows="1" Columns="2" />
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Value, ElementName=Slider}" Value="1">
            <Setter TargetName="Part4" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="Part3" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="Part2" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="Items" Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <Grid />
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

That's in plain xaml - I have a slider where you select number of panels to view and according to its value, I change Visibility of different panels and ItemsPanel as well.
If you are changing Visibility in code-behind, then you can change ItemsPanel of ItemsControl in code-behind as well.
So, when you need single panel you set it to simple Grid, if two panels: UniformGrid 1x2, if three panels: Grid with two equal rows and two equal columns and pay attention on Grid.Row, Grid.Column, Grid.ColumnSpan properties defined on panels. For four panels we use UniformGrid 2x2.
Hope, that helps.

Important: This will only work if your panels should always be in same order, and for example Part3 can't be visible if `Part2' is hidden. Otherwise, it's a bit more tricky - you will need to dynamically assigned content to parts.

UPD: To view DataTemplate on window you can use ContentControl:

<ContentControl Content="1">
   <ContentControl.ContentTemlate>
      ... Put DataTemplate here ...
   </ContentControl.ContentTemplate>
</ContentControl>