C# 在Xamarin表单中创建包含3列的ListView
我想在Xamarin表单中创建一个显示3列和N行的C# 在Xamarin表单中创建包含3列的ListView,c#,xamarin,xamarin.forms,C#,Xamarin,Xamarin.forms,我想在Xamarin表单中创建一个显示3列和N行的customListView(我将从web服务获取源代码)。每个单元格都有一个图标和一个说明。我找到了几个示例,但没有人使用列。根据需要,您可以创建一个列表视图,然后为每个项目创建一个网格,在其中定义3列。这将允许您保留ListView的额外功能,如PullToRefresh 如果您想要一个自动GridView类型控件,我确实根据ChaseFlorell的示例构建了一个,如本论坛帖子所示: 通过这种方式,它使数据可绑定,而不必显式定义每个数据 首
customListView
(我将从web服务获取源代码)。每个单元格都有一个图标和一个说明。我找到了几个示例,但没有人使用列。根据需要,您可以创建一个列表视图,然后为每个项目创建一个网格,在其中定义3列。这将允许您保留ListView的额外功能,如PullToRefresh
如果您想要一个自动GridView类型控件,我确实根据ChaseFlorell的示例构建了一个,如本论坛帖子所示:
通过这种方式,它使数据可绑定,而不必显式定义每个数据
首先是网格控件
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.Controls.GridView">
</Grid>
public partial class GridView : Grid
{
public GridView()
{
InitializeComponent();
for (var i = 0; i < MaxColumns; i++)
ColumnDefinitions.Add(new ColumnDefinition());
}
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create<GridView, object>(p => p.CommandParameter, null);
public static readonly BindableProperty CommandProperty = BindableProperty.Create<GridView, ICommand>(p => p.Command, null);
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create<GridView, IEnumerable<object>>(p => p.ItemsSource, null, BindingMode.OneWay, null, (bindable, oldValue, newValue) => { ((GridView)bindable).BuildTiles(newValue); });
private int _maxColumns = 2;
private float _tileHeight = 0;
public Type ItemTemplate { get; set; } = typeof(DocumentTypeTemplate);
public int MaxColumns
{
get { return _maxColumns; }
set { _maxColumns = value; }
}
public float TileHeight
{
get { return _tileHeight; }
set { _tileHeight = value; }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public IEnumerable<object> ItemsSource
{
get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public void BuildTiles(IEnumerable<object> tiles)
{
try
{
if (tiles == null || tiles.Count() == 0)
Children?.Clear();
// Wipe out the previous row definitions if they're there.
RowDefinitions?.Clear();
var enumerable = tiles as IList ?? tiles.ToList();
var numberOfRows = Math.Ceiling(enumerable.Count / (float)MaxColumns);
for (var i = 0; i < numberOfRows; i++)
RowDefinitions?.Add(new RowDefinition { Height = TileHeight });
for (var index = 0; index < enumerable.Count; index++)
{
var column = index % MaxColumns;
var row = (int)Math.Floor(index / (float)MaxColumns);
var tile = BuildTile(enumerable[index]);
Children?.Add(tile, column, row);
}
}
catch { // can throw exceptions if binding upon disposal
}
}
private Layout BuildTile(object item1)
{
var buildTile = (Layout)Activator.CreateInstance(ItemTemplate, item1);
buildTile.InputTransparent = false;
var tapGestureRecognizer = new TapGestureRecognizer
{
Command = Command,
CommandParameter = item1,
NumberOfTapsRequired = 1
};
buildTile?.GestureRecognizers.Add(tapGestureRecognizer);
return buildTile;
}
}
<control:GridView HorizontalOptions="FillAndExpand"
Grid.Row="1"
VerticalOptions="FillAndExpand"
RowSpacing="20"
ColumnSpacing="20"
MaxColumns="2"
ItemsSource="{Binding ListOfData}"
CommandParameter="{Binding}"
Command="{Binding ClickCommand}"
IsClippedToBounds="False">
<control:GridView.TileHeight>
<OnPlatform x:TypeArguments="x:Single"
iOS="60"
Android="60"
WinPhone="90" />
</control:GridView.TileHeight>
</control:GridView>
公共部分类GridView:Grid
{
公共网格视图()
{
初始化组件();
对于(变量i=0;ip.CommandParameter,null);
公共静态只读BindableProperty CommandProperty=BindableProperty.Create(p=>p.Command,null);
public static readonly BindableProperty ItemsSourceProperty=BindableProperty.Create(p=>p.ItemsSource,null,BindingMode.OneWay,null,(bindable,oldValue,newValue)=>{((GridView)bindable.BuildTiles(newValue);});
私有int_maxColumns=2;
私有浮动_tileHeight=0;
公共类型ItemTemplate{get;set;}=typeof(DocumentTypeTemplate);
公共整型MaxColumns
{
获取{return\u maxColumns;}
设置{u maxColumns=value;}
}
公众浮吊重量
{
获取{return\u tileHeight;}
设置{u tileHeight=value;}
}
公共对象命令参数
{
获取{return GetValue(CommandParameterProperty);}
set{SetValue(CommandParameterProperty,value);}
}
公共ICommand命令
{
获取{return(ICommand)GetValue(CommandProperty);}
set{SetValue(CommandProperty,value);}
}
公共IEnumerable ItemsSource
{
get{return(IEnumerable)GetValue(ItemsSourceProperty);}
set{SetValue(ItemsSourceProperty,value);}
}
公共空心建筑瓷砖(IEnumerable瓷砖)
{
尝试
{
如果(tiles==null | | tiles.Count()==0)
儿童?.Clear();
//删除前面的行定义(如果有)。
行定义?.Clear();
var enumerable=作为IList的tiles??tiles.ToList();
var numberOfRows=数学上限(enumerable.Count/(float)MaxColumns);
对于(变量i=0;i
然后定义一个模板
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.TypeTemplate">
<Label Text="{Binding Name}" />
</Grid>
public partial class TypeTemplate : Grid
{
public TypeTemplate()
{
InitializeComponent();
}
public TypeTemplate(object item)
{
InitializeComponent();
BindingContext = item;
}
}
公共部分类TypeTemplate:Grid
{
公共类型模板()
{
初始化组件();
}
公共类型模板(对象项)
{
初始化组件();
BindingContext=项目;
}
}
然后使用控件
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Mobile.Controls.GridView">
</Grid>
public partial class GridView : Grid
{
public GridView()
{
InitializeComponent();
for (var i = 0; i < MaxColumns; i++)
ColumnDefinitions.Add(new ColumnDefinition());
}
public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create<GridView, object>(p => p.CommandParameter, null);
public static readonly BindableProperty CommandProperty = BindableProperty.Create<GridView, ICommand>(p => p.Command, null);
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create<GridView, IEnumerable<object>>(p => p.ItemsSource, null, BindingMode.OneWay, null, (bindable, oldValue, newValue) => { ((GridView)bindable).BuildTiles(newValue); });
private int _maxColumns = 2;
private float _tileHeight = 0;
public Type ItemTemplate { get; set; } = typeof(DocumentTypeTemplate);
public int MaxColumns
{
get { return _maxColumns; }
set { _maxColumns = value; }
}
public float TileHeight
{
get { return _tileHeight; }
set { _tileHeight = value; }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public IEnumerable<object> ItemsSource
{
get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public void BuildTiles(IEnumerable<object> tiles)
{
try
{
if (tiles == null || tiles.Count() == 0)
Children?.Clear();
// Wipe out the previous row definitions if they're there.
RowDefinitions?.Clear();
var enumerable = tiles as IList ?? tiles.ToList();
var numberOfRows = Math.Ceiling(enumerable.Count / (float)MaxColumns);
for (var i = 0; i < numberOfRows; i++)
RowDefinitions?.Add(new RowDefinition { Height = TileHeight });
for (var index = 0; index < enumerable.Count; index++)
{
var column = index % MaxColumns;
var row = (int)Math.Floor(index / (float)MaxColumns);
var tile = BuildTile(enumerable[index]);
Children?.Add(tile, column, row);
}
}
catch { // can throw exceptions if binding upon disposal
}
}
private Layout BuildTile(object item1)
{
var buildTile = (Layout)Activator.CreateInstance(ItemTemplate, item1);
buildTile.InputTransparent = false;
var tapGestureRecognizer = new TapGestureRecognizer
{
Command = Command,
CommandParameter = item1,
NumberOfTapsRequired = 1
};
buildTile?.GestureRecognizers.Add(tapGestureRecognizer);
return buildTile;
}
}
<control:GridView HorizontalOptions="FillAndExpand"
Grid.Row="1"
VerticalOptions="FillAndExpand"
RowSpacing="20"
ColumnSpacing="20"
MaxColumns="2"
ItemsSource="{Binding ListOfData}"
CommandParameter="{Binding}"
Command="{Binding ClickCommand}"
IsClippedToBounds="False">
<control:GridView.TileHeight>
<OnPlatform x:TypeArguments="x:Single"
iOS="60"
Android="60"
WinPhone="90" />
</control:GridView.TileHeight>
</control:GridView>
一个比建议的更简单的解决方案是使用控件。它支持标题、行虚拟化、拉入刷新、按需加载和一系列其他有用的功能。您所说的“列”是什么意思?如果它们应该独立滚动,只需创建3个ListView并逐个放置即可。如果他们不应该,就在一行中的项目之间放置分隔符。我想要像这样的图标和描述来自JSON,这只是一个网格-使用网格布局好吗。最简单的方法就是使用。若网格高度超过页面高度,则将其包装到ScrollView中。但如果你想使用ListView,只需在一行中放置3个项目。我不会总是有完整的行项目,我可以有5个或7个项目,因此第一行中有3个项目,第二行中有2个项目,让我尝试使用ListView谢谢这对IOS非常简单和有用,但在Android的情况下,它对我不起作用,它与其他布局重叠,收集了大量数据