question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

programmatically create grid of WpfPlot controls #3

See original GitHub issue

Hi Scott, I have a class that creates a 12 x 8 grid which is partly shown below. The code in the class fills each cell with a ScottPlot.WpfPlot object as shown below. The WPF XAML code displays these plots nicely on a WPF grid, but… weirdy thing is that this code produces a rectangular plot outline box at (0,0) which is top left position even if I never call the setRow and setColumn, but just use the first code block below. If I click inside the rectangle, gridlines appear and axes are both labeled from -1 to +1. I’m wondering if there is a small bug that places a minimum of one rectangle on the grid? Other locations on the grid, where I add data using the second block of code below, plot the data nicely at the correct locations. Any thoughts?

First code block

        public ScottPlotGrid(Grid SPGrid, int numPlotColumns, int numPlotRows)
        {
            this.SPGrid = SPGrid;
            this.numPlotColumns = numPlotColumns;
            this.numPlotRows = numPlotRows;

            this.SPGrid.ColumnDefinitions.Clear();
            for (int i = 0; i < numPlotColumns; i++)
                this.SPGrid.ColumnDefinitions.Add(new ColumnDefinition());

            this.SPGrid.RowDefinitions.Clear();
            for (int i = 0; i < numPlotRows; i++)
                this.SPGrid.RowDefinitions.Add(new RowDefinition());

            wpfPlot = new ScottPlot.WpfPlot[numPlotColumns * numPlotRows];  // Create and array to hold the row x col ScottPlot objects

            for (int idx = 0; idx < (numPlotColumns * numPlotRows); idx++)  // Instantiate ScottPlot objects, and pop them into the grid
            {
                wpfPlot[idx] = new ScottPlot.WpfPlot();
                SPGrid.Children.Add(wpfPlot[idx]);
            }
        }

Second code block

        public void PlotCorrelation(int wellNum, int numCols, AviDataStor dataStor)
        {
            wpfPlot[wellNum].plt.PlotScatter(dataStor.dataColumns[0], dataStor.dataColumns[1], lineWidth: 0, markerSize: 3);
            wpfPlot[wellNum].plt.AxisAuto();
            wpfPlot[wellNum].Render();

            Grid.SetColumn(wpfPlot[wellNum], wellNum % numCols); // Convert linear well number into 2d row/column
            Grid.SetRow(wpfPlot[wellNum], wellNum / numCols);
        }

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:8 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
StendProgcommented, Mar 18, 2020

Then you do SPGrid.Children.Add(wpfPlot[idx]); and not specify Grid.Row, Grid.Column for them, they all dropped to (0, 0) element of Grid.

To follow WPF patterns you must avoid using code behind instead of xaml for markup. For that you can do: Make simple container for Grid element:

 public class PlotElement
    {
        public int X { get; set; }
        public int Y { get; set; }
        public ScottPlot.WpfPlot Control { get; set; }
    }

Make property in window class (code behind) to hold that elements:

        public List<PlotElement> plots { get; set; }

Fill that list in window constructor:

    plots = new List<PlotElement>();
    double[] xs = new double[] { 1, 2, 3 };
    double[] ys = new double[] { 5, 2, 7 };
    for (int x = 0; x < 12 ; x++) 
    {
        for (int y = 0; y < 8; y++)
        {
            PlotElement elem = new PlotElement()
            {
                X = x,
                Y = y,
                Control = new ScottPlot.WpfPlot()
            };
            elem.Control.plt.PlotScatter(xs, ys, lineWidth: 0, markerSize: 3);
            elem.Control.plt.AxisAuto();
            elem.Control.Render();
            plots.Add(elem);
     }            

and bind that list using xaml:

 <Grid>
        <ItemsControl ItemsSource="{Binding ElementName=controlGrid, Path=plots}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>
                            <RowDefinition/>                      
                        </Grid.RowDefinitions>
                    </Grid>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding Control}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemContainerStyle>
                <Style>
                    <Setter Property="Grid.Row" Value="{Binding Path=Y}"/>
                    <Setter Property="Grid.Column" Value="{Binding Path=X}"/>
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
    </Grid>

controlGrid is the window name, you can specify it in <window> section

1reaction
swhardencommented, Mar 18, 2020

This may be a better answer:

for (int idx = 0; idx < (numPlotColumns * numPlotRows); idx++)
{
    wpfPlot[idx] = new ScottPlot.WpfPlot();
    SPGrid.Children.Add(wpfPlot[idx]);
}

This code block is placing an empty ScottPlot into every grid square. If you don’t want a grid placed at (0, 0), modify the for loop to start at 1: int idx = 1

EDIT: this post relates to #257 and #267

Read more comments on GitHub >

github_iconTop Results From Across the Web

programmatically create grid of WpfPlot controls #2 #267
To fix this I have made a Grid and then placed your code within that (I have called the Grid SPGrid), along with...
Read more >
How to create a Grid in WPF Dynamically?
The Grid class in WPF represents a Grid control and with the vertical alignment, show grid lines, and background color property.
Read more >
WPF grid questions - setting one up programmatically
1 Answer 1 · It's easy, see msdn // Create the Grid Grid myGrid = new Grid(); myGrid.Width = 250; myGrid. · Set...
Read more >
How to: Create a Grid Element - WPF .NET Framework ...
The following example shows how to create and use an instance of Grid by using either Extensible Application Markup Language (XAML) or code....
Read more >
ScottPlot Changelog
WPF User Control: A ScottPlotWPF user control was created to allow provide a simple mouse-interactive ScottPlot control to WPF applications. It is not...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found