Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I bind arrays to columns in a WPF datagrid

I have a Log object that contains a list of Curve objects. Each curve has a Name property and an array of doubles. I want the Name to be in the column header and the data below it. I have a user control with a datagid. Here is the XAML;

<UserControl x:Class="WellLab.UI.LogViewer"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="500" d:DesignWidth="500">
<Grid>
    <StackPanel Height="Auto" HorizontalAlignment="Stretch" Margin="0" Name="stackPanel1" VerticalAlignment="Stretch" Width="Auto">
        <ToolBarTray Height="26" Name="toolBarTray1" Width="Auto" />
        <ScrollViewer Height="Auto" Name="scrollViewer1" Width="Auto" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible" CanContentScroll="True" Background="#E6ABA4A4">
            <DataGrid AutoGenerateColumns="True" Height="Auto" Name="logDataGrid" Width="Auto" ItemsSource="{Binding}" HorizontalAlignment="Left">
            </DataGrid>
        </ScrollViewer>
    </StackPanel>
</Grid>

In the code behind I have figured out how to create columns and name them, but I have not figured out how to bind the data.

public partial class LogViewer
{
    public LogViewer(Log log)
    {
        InitializeComponent();

        foreach (var curve in log.Curves)
        {
            var data = curve.GetData();
            var col = new DataGridTextColumn { Header = curve.Name };
            logDataGrid.Columns.Add(col);
        }
    }
}

I wont even show the code I tried to use to bind the array "data", since nothing even came close. I am sure I am missing something simple, but after hours of searching the web, I have to come begging for an answer.

like image 238
spainchaud Avatar asked Jan 20 '26 12:01

spainchaud


1 Answers

You need to pivot the log data into a collection of RowDataItem where each row contains a collection of double values, one for each Curve. At the same time you can extract the column names. So the data would end up like this.

public class PivotedLogData : ViewModelBase
{
    public PivotedLogData(Log log)
    {
        ColumnNames = log.Curves.Select(c => c.Name).ToList();

        int numRows = log.Curves.Max(c => c.Values.Count);

        var items = new List<RowDataItem>(numRows);

        for (int i = 0; i < numRows; i++)
        {
            items.Add(new RowDataItem(
                          log.Curves.Select(
                              curve => curve.Values.Count > i
                                           ? curve.Values[i]
                                           : (double?) null).ToList()));
        }

        Items = items;
    }

    public IList<string> ColumnNames { get; private set; }
    public IEnumerable<RowDataItem> Items { get; private set; }
}

public class RowDataItem
{
    public RowDataItem(IList<double?> values)
    {
        Values = values;
    }

    public IList<double?> Values { get; private set; }
}

Then you would create DataGridTextColumn items as above but with a suitable binding

var pivoted = new PivotedLogData(log);

int columnIndex = 0;

foreach (var name in pivoted .ColumnName)
{
    dataGrid.Columns.Add(
        new DataGridTextColumn
            {
                Header = name,
                Binding = new Binding(string.Format("Values[{0}]", columnIndex++))
            });
}

Now bind the data to the grid

dataGrid.ItemsSource = pivoted.Items;
like image 79
Phil Avatar answered Jan 22 '26 05:01

Phil



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!