你所拥有的不会起作用,因为Silverlight将每个项目(DataTemplate的每个实例)都包装在一个ListBoxItem中,而Grid.Column和Grid.Row附加属性需要应用于该ListBoxItem,而不是成为该ListBoxItem内容的TextBox。
好消息是,你可以使用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="" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Grid />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</local:GriderrificBox>
这段代码存在(至少)两个主要问题:首先,即使控件仅适用于网格面板,您仍需要在XAML中显式指定ItemsPanel;其次,绑定路径被硬编码到代码中。第一个问题可以通过使用正常的控件默认样式机制来解决,第二个问题可以通过定义属性,例如RowBindingPath和ColumnBindingPath,供PrepareItemForContainerOverride查询而不是使用硬编码路径来解决。希望这足以帮助您入门!