2

Каков наилучший способ отображения многомерных данных в WPF? Я не буду знать размер/форму данных до времени выполнения. В идеале я хотел бы использовать привязку данных, но это не строгое требование. Я думал о какой-то сетке, но я не знаю, как динамически привязываться к данным и подсчитывать количество строк и столбцов. Предложения и примеры, пожалуйста?Отображение многомерных данных в WPF

+0

Уточнение: по размеру/форме Я имею в виду MxN, а не круги/квадраты. Я имею дело с данными массива, которые могут быть от 1D до 6D, которые я хочу отображать в виде таблицы (больше 2D должен просто отображаться последовательно в «таблице»). Я не имею дело с зубчатыми массивами или разреженными матрицами. Мой вопрос действительно, что является хорошим контролем для реализации этой «таблицы». – KrisTrip

+0

Еще одно уточнение: мне также нужно, чтобы он работал как отличный стол. Например, мне нужно иметь возможность выбирать прямоугольник данных для копирования/вставки с/на. – KrisTrip

+0

Вы знаете, не рассчитывайте на огромный ответ, если вы не дадите баллы за правильные ответы на свой вопрос (нет сомнений, что это правильно) :) –

ответ

2

Звуки, как будто вы хотите Excel-подобный интерфейс для 2D массивов с возможностью редактирования. Для других измерений вам придется придумать вкладки или серию comboboxes.

Ознакомьтесь с набором данных WPF Toolkit DataGrid. Существует опция автоматического генерации столбцов. Поэкспериментируйте с этим.

Однако у вас будет некоторый код, чтобы иметь дело с другими измерениями, поскольку Datagrid может представлять только 2D-данные.

Corey

Edit: (04/28/2010) Вот рабочий раствор.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows; 
using System.Windows.Data; 
using Microsoft.Windows.Controls; 

namespace WpfApplication2 
{ 
    public partial class MainWindow : Window 
    { 
    public List<List<object>> TheData { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 

     // Generate some random data 
     Random r = new Random(); 

     TheData = new List<List<object>> 
     { 
      new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) }, 
      new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) }, 
      new List<object> { r.Next(100), r.Next(100), r.Next(100) }, 
      new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) }, 
      new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100) }, 
      new List<object> { r.Next(100), r.Next(100), r.Next(100),r.Next(100), r.Next(100) } 
     }; 

     // Now bind data to the grid 
     // We need at least one element 
     if (TheData.Count > 0) 
     { 
      // Find the longest row so we create enough columns 
      var max = TheData.Max(c => c.Count); 

      for (var i = 0; i < max; i++) 
      { 
       TheGrid.Columns.Add(
        new DataGridTextColumn 
        { 
         Header = string.Format("Column: {0:00}", i), 
         Binding = new Binding(string.Format("[{0}]", i)) 
        } 
        ); 
      } 
     } 

     TheGrid.ItemsSource = TheData; 
    } 
} 

}

Часть XAML ...

<Window x:Class="WpfApplication2.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit" 
    Title="GridTest"> 
<Grid x:Name="LayoutGrid"> 
    <toolkit:DataGrid x:Name="TheGrid" 
         AutoGenerateColumns="False" 
         IsReadOnly="False" 
         CanUserAddRows="False"/> 
</Grid> 

Некоторые вещи, чтобы отметить о таком подходе, если разрешить редактирование данных и позволяют неровные массивы, вам нужно будет для нового нового списка на коротких строках.

Что касается 2D-данных, вам потребуется какая-то опция для выбора другого измерения, поскольку datagrid может представлять только данные 2D.

+0

Это именно то, о чем я говорю! WPF Toolkit DataGrid выглядит многообещающим. – KrisTrip

0

Я сделал что-то подобное, когда данные были списком или списками или массивом массивов. Не знаете, как заблокировано в вас использование многомерных массивов по сравнению с этим методом для данных типа «сетка».

Вот как я связан с списком списков.

 <Resources> 
     <DataTemplate x:Key="GridDtInner"> 
      <TextBlock Text="{Binding YourProperty}"/> 
     </DataTemplate> 
     <DataTemplate x:Key="GridDtOuter"> 
      <ItemsControl ItemsSource="{Binding}" ItemTemplate="{DynamicResource GridDtInner}" /> 
     </DataTemplate>  
     </Resources> 
     <ItemsControl ItemTemplate="{DynamicResource GridDtOuter}" ItemsSource="{Binding YourList, Mode=Default}"> 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <StackPanel Orientation="Horizontal"/> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
     </ItemsControl> 

Очевидно, что я сократил все для краткости, но, надеюсь, это имеет смысл.

С уважением,

Майк McAulay

0

Я сделал что-то очень похожее, но, скорее всего, в совершенно иной отрасли, чем вы работаете.

Когда вы говорите, размер/форма данных, я предполагаю, что вы не в буквальном смысле говорите о кругах против квадратов, но вместо этого говорите, что у вас есть матрица данных NxM, и вы не знаете, что N и M до времени исполнения. Я также предполагаю, что вы хотите отобразить какой-то текст в каждой ячейке матрицы NxM.

Обратите внимание, что следующий XAML был изменен из моего кода и не был протестирован, но я хотел дать вам общее представление о том, как я это сделал.

 <ListBox Width="300" Height="300" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding Cells}"> 
      <ListBox.ItemsPanel> 
       <ItemsPanelTemplate> 
        <WrapPanel Width="Auto" Height="Auto" ItemWidth="{Binding CellBoundary}" ItemHeight="{Binding CellBoundary}"/> 
       </ItemsPanelTemplate> 
      </ListBox.ItemsPanel> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Width="{Binding CellDiameter}" Height="{Binding CellDiameter}" Text="{Binding CellValue}"></TextBlock> 
       </DataTemplate>      
      </ListBox.ItemTemplate> 
     </ListBox> 

Я изменил ItemsBox's ItemsPanel, чтобы просто быть ListBox. Таким образом, если у вас есть матрица NxM (она также может быть разреженной), вы рассматриваете ее как вектор с ячейками NxM. Каждая ячейка фактически является элементом в ListBox.

Далее вы установите DataTemplate для каждого элемента ListBox просто быть TextBlock, где размер в TextBlock является привязкой к данным и на экране отображается значение в CellValue члена ваших клеток, что является ObservableCollection<double> или аналогичный, с привязкой к данным в Cells.

Единственное, что вам нужно сделать в этот момент в коде, это выяснить, что такое N и M, и сделать необходимую математику для вычисления размера ListBox (может быть внутри ViewBox, чтобы сделать его масштабируемым), так что значения отображаются соответствующим образом. Очевидно, что вам нужно будет изменить свои жестко заданные значения на то, что нужно сделать.

Этот подход кажется самым простым для меня вокруг моего мозга, поэтому я использовал его для своих вещей.

Следует также добавить, что для создания разреженной матрицы вы установите значение CellValue равным 0, но вы также можете использовать DataTrigger, чтобы сделать TextBlocks невидимым, если значение равно 0, что дает иллюзию редкой матрица.

1

Я думаю, что лучшим решением для вас, чтобы просто использовать TreeView :), если вы используете MVVM, это самый блестящий учебник о TreeView я нашел: http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx

Пожалуйста, держите меня в курсе, если вам нужно больше Информация.

+0

TreeView - не лучшее решение для меня. Это данные массива, которые должны отображаться таблично-подобным образом (например, сетка excel или что-то еще) – KrisTrip

+0

В этом случае у меня есть 2 альтернативы для вас. Во-первых: вы можете просмотреть дерево шаблонов так же, как и таблицу (я настаиваю на использовании TreeView, потому что это очень легко связывается с иерархическими структурами данных). Во-вторых: вы можете использовать только обычную сетку со связанными строками/столбцами или список со связанными, шаблонизированными элементами списка. Если бы я был твоим, я бы выбрал первое решение :) С уважением, Петр. –

+0

Мне также нужно, чтобы он играл как отличный стол. Например, мне нужно иметь возможность выбирать прямоугольник данных для копирования/вставки с/на. Я не думаю, что TreeView может работать с этим типом функциональности. – KrisTrip

0

Я только что нашел DataGrid в WPF Toolkit, который показывает некоторый потенциал.Это, по крайней мере, позволяет выбирать отдельные ячейки. Я отправлю код, когда выясню привязку данных.
http://wpf.codeplex.com/releases/view/40535
http://windowsclient.net/wpf/wpf35/wpf-35sp1-toolkit-datagrid-feature-walkthrough.aspx

Смежные вопросы