2013-05-16 3 views
0

Я хочу построить ui с динамической сеткой. По крайней мере, я думаю, что сетка - это путь. Элементы управления каждой соты должны быть одинаковыми, т. Е. a TextBox.Динамический ui с строками и столбцами

Каждая строка может иметь различное число клеток, и я думал об использовании ColumnSpan свойства, чтобы сделать пользовательский интерфейс выглядеть

First row, 2 cells 
Second row, 3 cells 
Third row, 1 cell 

Каждая ячейка должна быть частью F.E. ObservableCollection<MyCellClass> и должны иметь такие свойства, как , Column, Columnspan, Text.

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

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

ответ

2

Вы можете использовать сетку как ItemsPanel элемента ItemsControl и привязать свойство ItemsSource к вашему ObservableCollection.

Предполагая, что ваш класс клетка выглядит следующим образом:

public class Cell 
{ 
    public int Column { get; set; } 
    public int ColumnSpan { get; set; } 
    public int Row { get; set; } 
    public int RowSpan { get; set; } 
    public string Text { get; set; } 
} 

XAML может быть написано, как показано ниже:

<ItemsControl ItemsSource="{Binding}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Grid> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
        <ColumnDefinition/> 
       </Grid.ColumnDefinitions> 
       <Grid.RowDefinitions> 
        <RowDefinition/> 
        <RowDefinition/> 
        <RowDefinition/> 
        <RowDefinition/> 
       </Grid.RowDefinitions> 
      </Grid> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemContainerStyle> 
     <Style TargetType="ContentPresenter"> 
      <Setter Property="Grid.Column" Value="{Binding Column}"/> 
      <Setter Property="Grid.ColumnSpan" Value="{Binding ColumnSpan}"/> 
      <Setter Property="Grid.Row" Value="{Binding Row}"/> 
      <Setter Property="Grid.RowSpan" Value="{Binding RowSpan}"/> 
     </Style> 
    </ItemsControl.ItemContainerStyle> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <TextBox Text="{Binding Text}"/> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

Следующий фрагмент кода будет инициализировать две клетки ItemsControl:

public MainWindow() 
{ 
    InitializeComponent(); 

    var cells = new ObservableCollection<Cell>(); 
    cells.Add(new Cell { Column = 0, Row = 0, ColumnSpan = 1, RowSpan = 1, Text = "Cell 1" }); 
    cells.Add(new Cell { Column = 2, Row = 2, ColumnSpan = 2, RowSpan = 1, Text = "Cell 2" }); 
    DataContext = cells; 
} 
+0

Благодарим вас за это элегантное решение. –

0

Почему бы не использовать что-то вроде этого?

public class ItemVm 
{ 
    // here you can put your desired properties, 
    // although you won't need something like ColumnsSpan etc. 
} 

В базовой структуры (ViewModel) для вашей сетки можно использовать следующее свойство:

public ObservableCollection<ObservableCollection<ItemVm>> Rows { get; } // just an illustration 

Теперь вам нужно только ListView (или нечто подобное), чьи ItemTemplate снова является ListView (или что-то похожее). ItemTemplate внутреннего ListView будет наглядным изображением ItemVm.

Обратите внимание, что я описываю подход в соответствии с шаблоном MVVM. Таким образом, вам понадобится базовый класс для моделей viewmodels. Но вы можете найти множество фреймворков на WWW.

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