我需要在网格中显示List<string>
。
我需要能够在其中显示每个字符串,对于这个问题,让我们说TextBlock
。
我尝试使用ItemsControl
,但它没有按我需要的方式工作,所以我考虑将网格控件子类化为ItemGrid把它作为DataContext
和IEnumerable
(并忽略其他任何内容),并采用ItemTemplate
来告诉控件如何显示内容。
我知道如何使用DataContext
来显示内容,但我不知道如何在控件中实现模板。
到目前为止,我对控制的想法是:
public class ItemGrid : Grid {
public static readonly DependencyProperty
ColumnCountProperty = DependencyProperty.Register(
"ColumnCount",
typeof(int),
typeof(ItemGrid),
new PropertyMetadata( 1, OnColumnCountChanged ) ),
ItemSourceProperty = DependencyProperty.Register(
"ItemSource",
typeof( IEnumerable<object> ),
typeof( ItemGrid ),
new PropertyMetadata( null, OnItemSourceChanged ) );
private static void OnColumnsChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e ) {
ItemGrid IG = sender as ItemGrid;
IG.ColumnDefinitions.Clear( );
for ( int c = 0; c < ( int )e.NewValue; c++ )
IG.ColumnDefinitions.Add( new ColumnDefinition( ) {
Width = new GridLength( 1, GridUnitType.Star ) } );
OnItemSourceChanged(
sender,
new DependencyPropertyChangedEventArgs(
ItemSourceProperty, IG.ItemSource, IG.ItemSource ) );
}
private static void OnItemSourceChanged(
DependencyObject sender, DependencyPropertyChangedEventArgs e ) {
ItemGrid IG = sender as ItemGrid;
int x = 0, rows;
//This is the stub.
//this is where the objects would be passed on to the DataTemplate.
IEnumerable<UIElement> Children =
( e.NewValue as IEnumerable<object> ).Select( Child => new UIElement( ) );
foreach( UIElement Child in Children ) {
IG.Children.Add( Child );
x = IG.Children.IndexOf( Child );
SetColumn( Child, x % IG.ColumnCount );
SetRow( Child, x / IG.ColumnCount );
}
rows = IG.Children.Cast<UIElement>( ).Max( Child => GetRow( Child ) ) + 1;
for ( x = 0; x < rows; x++ )
IG.RowDefinitions.Add(
new RowDefinition( ) {
Height = new GridLength( 1, GridUnitType.Star ) } );
}
/// <summary>
/// Get or Set Items Source.
/// </summary>
public IEnumerable<object> ItemSource {
get { return this.GetValue( ItemSourceProperty ) as IEnumerable<object>; }
set { this.SetValue( ItemSourceProperty, value ); }
}
/// <summary>
/// Get or Set Number of Columns.
/// </summary>
public int ColumnCount {
get { return ( int )this.GetValue( ColumnCountProperty ); }
set { this.SetValue( ColumnCountProperty, value ); }
}
}
在OnItemSourceChanged
方法中有一个存根,用于将对象选择为IEnumerable<UIElement>
,然后将其分发到网格中。
这是我需要学习如何实现DataTemplate的地方,以及我需要帮助的地方。
我想尽可能地保留在XAML中,这样我基本上可以这样做:
<Controls:ItemGrid ColumnCount = "2" ItemSource = "{Binding Foo}">
<Controls:ItemGrid.Template>
<DataTemplate>
<TextBlock Text = "{Binding Bar}"/>
</DataTemplate>
</Controls:ItemGrid.Template>
</Controls:ItemGrid>
在这样做的过程中,网格将填充后面的代码。 再一次 - 我尝试过使用ItemsControl,但它不起作用(即使得到articles I've read的所有帮助,我也无法获得它以我需要的方式工作。)
如何在此控件中实现模板?
为清楚起见,这是我正在寻找的东西:
我能够找到答案here。
答案 0 :(得分:0)
您需要使用ItemsControl,但将ItemsPanel设置为2列UniformGrid,并将ItemTemplate设置为具有适当绑定的TextBlock。当控件不够高时,您还想将整个事物包装在ScrollViewer中,但您还要将ItemsControl的垂直对齐设置为top,以便当父ScrollViewer太高时,元素不会伸展出来:
<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl Name="myGrid" VerticalAlignment="Top">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontSize="50" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TextAlignment="Center" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
如果您只想要显示2行,则丢失ScrollViewer,将ItemControl的垂直对齐设置为拉伸并在UniformGrid中指定Rows="2"
:
<ItemsControl Name="myGrid">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="2" Rows="2" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontSize="50" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TextAlignment="Center" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>