动态添加填充有绑定文本框的网格行
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>
我最近完成了我的第一个 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>