Динамическое добавление строк сетки, заполненных связанными текстовыми полями

Я недавно закончил свое первое приложение в стиле MVVM, в котором было заданное количество столбцов / строк и элементов управления.

То, что я пытаюсь сделать сейчас, основано на количестве элементов в observableCollection<myClass>добавьте строку в основную сетку, заполненную текстовыми полями, привязанными к свойствам в каждом элементе observableCollection.

Так, например, вот пример модели представления:

public class VehiclesViewModel : ObservableObject
{
    private ObservableCollection<Vehicle> _vehCollection;
    public ObservableCollection<Vehicle> VehCollection
    {
        get
        {
            return this._vehCollection;
        }

        set
        {
            if (null != value)
            {
                this._vehCollection= value;
                OnPropertyChanged("VehCollection");
            }
        }
    }
}

Вот класс модели:

public class Vehicle : INotifyPropertyChanged
{

    private double _alt;
    public double Alt 
    {
        get { return this._alt; }
        set
        {
            this._alt = value;
            base.OnPropertyChanged("Alt");
        }
    }

    private double _depth;        
    public string Depth
    {
        get { return this._depth; }
        set
        {
            this._depth = value;
            base.OnPropertyChanged("Depth");
        }
    }
}

Вот пример вида:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="39.8" />
        <ColumnDefinition Width="39.8" />
        <ColumnDefinition Width="80" />
        <ColumnDefinition Width="80" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="26" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <ItemsControl ItemsSource="{Binding VehCollection}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBox Text="{Binding Alt}" Grid.Column="0" Grid.ColumnSpan="2"/>
                    <TextBox Text="{Binding Depth}"
                            Grid.Column="3"
                            Grid.ColumnSpan="2" />
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

Допустим, какая-то функция, которую я вызываю, добавляет три элемента в _vehCollection. Когда это происходит, я хочу, чтобы сетка добавляла три строки под существующими строками, причем каждая из этих трех содержит два текстовых поля, которые привязаны к свойствам в моем классе Vehicle для каждого из этих элементов. Я также хочу указать Grid.Column они появятся в (они будут появляться горизонтально в том же ряду, а не вертикально).

Я пытался с помощью ItemsControl, что заставляет текстовые поля появляться, но это появляется в верхнем левом углу сетки. Я не могу заставить его появляться ниже существующих строк.

Примечание: у меня намного больше определений строк / столбцов и других элементов управления внутри основной сетки. Я не хочу переделывать все это.

2 ответа

Решение

Вы можете использовать ItemsControl с Grid в качестве ItemPanel. Хотя будет немного сложнее динамически добавить RowDefinitions в Grid. Пожалуйста, ознакомьтесь со следующим сообщением в блоге для получения дополнительной информации и примера: http://blog.scottlogic.com/2010/11/15/using-a-grid-as-the-panel-for-an-itemscontrol.html.

Более простой подход - использовать ItemsControl с ItemTemplate, который содержит Grid с нужным количеством столбцов. Затем вы можете добавить свойство Column типа int в свой класс Vehicle и связать вложенное свойство Grid.Column вашей StackPanel в ItemTemplate с этим:

     <ItemsControl ItemsSource="{Binding VehCollection}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="39.8" />
                        <ColumnDefinition Width="39.8" />
                        <ColumnDefinition Width="80"  />
                        <ColumnDefinition Width="80" />
                    </Grid.ColumnDefinitions>
                    <StackPanel Orientation="Horizontal" Grid.Column="{Binding Column}">
                        <TextBox Text="{Binding Alt}" />
                        <TextBox Text="{Binding Depth}" />
                    </StackPanel>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

Если каждый TextBox должен быть в своем собственном столбце, вы можете добавить свойство "Column" для каждого TextBox в свой класс Vehicle и привязать их по отдельности:

<TextBox Text="{Binding Alt}" Grid.Column="{Binding AltColumn}" />
<TextBox Text="{Binding Depth}" Grid.Column="{Binding Deptholumn}" />

Хорошо, что делает ваш элемент управления, говорит, показать список элементов в ячейке сетки 0,0

все, что вам нужно, это поместить сетку в список. Самый простой способ - это GridView.

например

<ListView ItemsSource="{Binding VehCollection}">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Depth}"/>
            <GridViewColumn DisplayMemberBinding="{Binding Alt}"/>
            <GridViewColumn/>
            <GridViewColumn/>
        </GridView>
    </ListView.View>

Другой вариант - установить шаблон элемента в сетку.

<ItemsControl ItemsSource="{Binding VehCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="39.8" />
                    <ColumnDefinition Width="39.8" />
                    <ColumnDefinition Width="80"  />
                    <ColumnDefinition Width="80" />
                </Grid.ColumnDefinitions>
                <TextBox Text="{Binding Alt}" Grid.Column="0"/>
                <TextBox Text="{Binding Depth}"  Grid.Column="1"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>

</ItemsControl>
Другие вопросы по тегам