动态添加填充有绑定文本框的网格行

Dynamically adding grid rows filled with bound textboxes

我最近完成了我的第一个 MVVM 风格的应用程序,其中有一定数量的 columns/rows 和控件。

我现在要做的是,根据 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");
            }
        }
    }
}

这是模型 class:

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>

假设我调用的某个函数将 three 项添加到 _vehCollection。发生这种情况时,我希望网格在现有行下方添加 三行 行,这三行中的每一行都包含两个文本框,这些文本框绑定到我的 Vehicle class 中的属性每一项。我还想指定 Grid.Column 它们将出现在(它们将水平出现在同一行上,而不是垂直出现)。

我尝试使用 ItemsControl,它确实使文本框出现,但它出现在网格的左上角。我无法让它显示在现有行的下方。

注意:我在主网格中有更多 rows/column 定义和其他控件。我不想重做所有这些。

您可以使用带有网格的 ItemsControl 作为其 ItemPanel。不过,将 RowDefinitions 动态添加到 Grid 会有点棘手。请查看以下博客 post 以获取更多信息和示例:http://blog.scottlogic.com/2010/11/15/using-a-grid-as-the-panel-for-an-itemscontrol.html.

一种更简单的方法是将 ItemsControl 与 ItemTemplate 一起使用,该 ItemTemplate 包含具有所需列数的 Grid。然后,您可以将 int 类型的 Column 属性 添加到您的 Vehicle class 并将 ItemTemplate 中 StackPanel 的 属性 附加 Grid.Column 绑定到此:

     <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 都应该在其自己的列中,您可以将每个 TextBox 添加一个 "Column" 属性 到您的 Vehicle class 并分别绑定到它们:

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

好的,您的 Items 控件正在执行的操作是在 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>