是否可以做这样的事情:
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}" Grid.Column="{Binding Column}" Grid.Row="{Binding Row}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
项目源类似于具有文本,列和行属性的对象列表。
这可能吗?我真的希望我的数据网格是数据绑定的。
答案 0 :(得分:3)
你所拥有的东西将无法工作,因为Silverlight将每个项目 - 每个DataTemplate实例 - 包装在一个ListBoxItem中,而Grid.Column和Grid.Row附加的属性需要应用于该ListBoxItem,而不是TextBox,它成为该ListBoxItem的内容。
好消息是你可以使用ListBox.ItemContainerStyle在隐式ListBoxItem上设置属性。
坏消息是ItemContainerStyle不支持绑定。因此,您无法使用它将Grid.Column和Grid.Row附加属性设置为手头数据项的属性。
我使用的一个解决方案是继承ListBox并在PrepareContainerForItemOverride中设置绑定。这是一个非常粗糙,硬连线的例子:
public class GriderrificBox : ListBox
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);
FrameworkElement fe = element as FrameworkElement;
if (fe != null)
{
BindingOperations.SetBinding(fe, Grid.RowProperty,
new Binding { Source = item, Path = new PropertyPath("Row") });
BindingOperations.SetBinding(fe, Grid.ColumnProperty,
new Binding { Source = item, Path = new PropertyPath("Column") });
}
}
}
用法:
<local:GriderrificBox>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</local:GriderrificBox>
此代码至少有两个主要的uglinesses:首先,您仍需要在XAML中明确指定ItemsPanel,即使该控件仅适用于Grid面板;第二,绑定路径硬连线到代码中。第一个可以通过使用普通控件默认样式机制来解决,第二个可以通过定义属性,如RowBindingPath和ColumnBindingPath,PrepareItemForContainerOverride可以参考而不是使用硬连线路径。希望足够让你去!
答案 1 :(得分:2)
Grid
仅适用于您尝试将其用于此处的用法。在开始向单元格分配元素之前,它期望预先定义可用行和列的集合。
如果您尝试创建一个使用水平和垂直空间的列表框,那么Silverlight Toolkit中的WrapPanel
可能是更好的基础。
另一方面,如果您尝试创建“数据网格”,请考虑对模型中每行的列进行转置或分组,然后您可以使用DataGrid
代替ListBox
答案 2 :(得分:2)
我找到了另一个有趣的解决方案: http://www.scottlogic.co.uk/blog/colin/2010/11/using-a-grid-as-the-panel-for-an-itemscontrol/
示例是使用ItemsCountrol
完成的 - 但我很确定它也适用于ListBox
结果如下:
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- use the ItemsPerRow attached property to dynamically add rows -->
<Grid local:GridUtils.ItemsPerRow="1"
ShowGridLines="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
并且确实需要实现local:GridUtils.ItemsPerRow
附加属性。
答案 3 :(得分:2)
仅当您知道需要多少行和列且仅在Silverlight 5中时才会有效。(您无法在silverlight 4中的setter属性中绑定值。)
<Grid x:Name="LayoutRoot" Background="White">
<ItemsControl x:Name="ic" Background="#FFE25454">
<ItemsControl.Resources>
<Style TargetType="ContentPresenter">
<Setter Property="Grid.Row" Value="{Binding X}"/>
<Setter Property="Grid.Column" Value="{Binding Y}"/>
</Style>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions></Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding text}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
答案 4 :(得分:0)
如果您有兴趣在将来版本的Silverlight中支持此类场景,请投票选择porting of Adobe Flex Grid layout,这将在此类场景中完美运行
答案 5 :(得分:-1)
您只需要为Grid创建两个附加属性(类似于ColumnsNumber和RowsNumber,它们将填充ColumnDefinitions和RowDefenitions集合)。然后覆盖ItemsControl中的默认ItemContainerStyle(因为ItemsControl中的所有项目都由ContentPresenters包装)。代码示例:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid
behavior:GridBehavior.ColumnsNumber="{Binding}"
behavior:GridBehavior.RowsNumber="{Binding}">
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemsSource>
<Binding />
</ItemsControl.ItemsSource>
<ItemsControl.ItemTemplate>
<DataTemplate />
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Grid.Column" Value="{Binding}" />
<Setter Property="Grid.Row" Value="{Binding}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>