如何在WPF数据表格中将数组绑定到列?

3

我有一个Log对象,其中包含一组Curve对象。每个曲线都有一个Name属性和一个双精度数组。我希望将Name放在列标题中,并在其下方显示数据。我有一个带有datagrid的用户控件。以下是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>

在代码后台,我已经知道如何创建和命名列,但是我还没有弄清楚如何绑定数据。
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);
        }
    }
}

我甚至不会展示我尝试使用来绑定数组"data"的代码,因为什么都没接近成功。我相信我错过了一些简单的东西,但是在搜索了几个小时之后,我必须乞求一个答案。


可能是重复的问题:如何在WPF DataGrid中显示数组元素? - H.B.
@dbaseman:这对于数组没有帮助,因为没有内置的逻辑来处理它们。 - H.B.
@H.B. 感谢您的澄清。我误解了问题。 - McGarnagle
通常情况下,当您将数组绑定到DataGrid时,数组的每个成员都是一行,而不是一列。在您的情况下,您可以有两列,一列用于名称,另一列用于数据。如果数据本身就是一个数组,那么您可以创建一个模板列,使用某种类型的ItemsControl来绑定到每个数据数组。 - Trevor Elliott
Moozhe关于数组中每个成员都是一个行的说法是正确的。这就是我一直得到的结果,但这对我没有用。我期望最终的解决方案有两个数据网格。一个是用于标题的,即与曲线相关联的名称,另一个是在滚动查看器中放置曲线数据的单独数据网格。曲线数据是一个包含数千个元素的double数组。 - spainchaud
1个回答

3
你需要将日志数据转换为一组RowDataItem,其中每行包含一组双精度值,每个值对应一个Curve。同时,你可以提取列名。因此,数据最终会像这样。
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; }
}

然后,您将创建与适当绑定的DataGridTextColumn项目,如上所示。
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++))
            });
}

现在将数据绑定到网格中。
dataGrid.ItemsSource = pivoted.Items;

感谢您提供的示例,它完美地运行了。不幸的是,出现了两个问题。数据网格速度太慢了。一个包含25,000个条目的网格需要10秒才能打开。这样小的数字应该几乎立即打开。此外,我需要能够删除日志中的单个曲线,并看到网格中相应列消失。 - spainchaud
进一步解释一下,我正在尝试模拟一个现有的程序(Windows Forms),该程序使用类似于我所拥有的数据结构。那个程序可以非常快速地打开更大的数据集。我认为它可能正在使用第三方数据网格控件。我将不得不问作者他是如何做到的。 - spainchaud
我已经测试了10个包含250,000条目的曲线。枢轴点花费了500毫秒(可能可以改进)。网格显示瞬间完成。响应事件(CurveRemoved)并删除一列及其所有相关值应该很简单。 - Phil
我通过将数据网格放入DockPanel而不是StackPanel来大大加快了速度,这也为我提供了滚动条。我计时了4个案例,包括旋转和填充数据网格。以下是我的时间:打开日志MPR模式。因此,较小的情况约为2.5秒。也许我可以找到另一个加速方法。 所需时间:00:00:04.69 点数:42500 打开日志DTKRes模式 所需时间:00:00:02.92 点数:22500 打开日志RADRAngleMM 所需时间:00:00:02.51 点数:22500 打开日志RADRTargMM 所需时间:00:00:02.32 点数:22500 - spainchaud
我将在几分钟内去上班,我可以找出他们如何填充他们的WinForms控件。 - spainchaud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接