![](/img/trans.png)
[英]How can I select an item in a ListView in Xamarin.Forms with XAML
[英]How can I display items in a ListView horizontally in Xamarin.forms xaml?
我在ListView
顯示SQLite對象列表,但我希望它們水平顯示。 所以不是這樣的:
| longitem |
| item |
| evenlongeritem |
| item |
| longeritem |
我要這個:
| longitem item |
| evenlongeritem |
| item longeritem |
重要的是,這些項目的寬度可以不同,因此只需將列表分成一定數量的列就可以得到改進,但並不理想。 我也不知道物品的數量。
這是我目前的代碼:
<ListView x:Name="inactiveList" VerticalOptions="Start" ItemTapped="PutBack">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" TextColor="Black">
<TextCell.ContextActions>
<MenuItem Command="{Binding Source={x:Reference ListPage}, Path=DeleteListItem}" CommandParameter="{Binding .}" Text="delete" />
</TextCell.ContextActions>
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
代碼背后:
public ListPage()
{
InitializeComponent();
ObservableCollection<ListItem> activeItems =
new ObservableCollection<ListItem>(
App.ListItemRepo.GetActiveListItems());
activeList.ItemsSource = activeItems;
...
我嘗試將ViewCell
包裝在水平StackLayout
,但是我收到了這個錯誤:
未處理的異常:System.InvalidCastException:指定的強制轉換無效。
我不確定該錯誤是什么意思,但我認為不可能在DataTemplate
添加StackLayout
。 我也無法使ListView
水平。
-
我終於可以將簡單的標簽水平列出,但現在我無法重新創建垂直ListView內置的水龍頭和長按動作。 這可能嗎?
ListView.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns:local="clr-namespace:Myapp">
<!-- ... -->
<local:WrapLayout x:Name="inactiveList" ItemsSource="{Binding .}" Spacing="5" />
ListView.xaml.cs
using Myapp.Models;
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Linq;
using SQLite;
using System.Threading.Tasks;
using System.IO;
using Xamarin.Forms;
using System.Diagnostics;
using DLToolkit.Forms.Controls;
namespace Myapp
{
public partial class ListPage
{
...
public ListPage()
{
InitializeComponent();
ObservableCollection<ListItem> inactiveItems =
new ObservableCollection<ListItem>(
App.ListItemRepo.GetInactiveListItems());
inactiveList.ItemsSource = inactiveItems;
inactiveList.HeightRequest = 50 * inactiveItems.Count;
}
...
}
public class WrapLayout : Layout<View>
{
public ObservableCollection<ListItem> ItemsSource
{
get { return (ObservableCollection<ListItem>)GetValue(ItemSourceProperty); }
set { SetValue(ItemSourceProperty, value); }
}
public static readonly BindableProperty ItemSourceProperty =
BindableProperty.Create
(
"ItemsSource",
typeof(ObservableCollection<ListItem>),
typeof(WrapLayout),
propertyChanged: (bindable, oldvalue, newvalue) => ((WrapLayout)bindable).AddViews()
);
void AddViews()
{
Children.Clear();
foreach (ListItem s in ItemsSource)
{
Button button = new Button();
button.BackgroundColor = Color.Red;
button.Text = s.Name;
button.TextColor = Color.Black;
button.Clicked = "{Binding Source={x:Reference ListPage}, Path=PutBack}";
Children.Add(button);
}
}
public static readonly BindableProperty SpacingProperty =
BindableProperty.Create
(
"Spacing",
typeof(double),
typeof(WrapLayout),
10.0,
propertyChanged: (bindable, oldvalue, newvalue) => ((WrapLayout)bindable).OnSizeChanged()
);
public double Spacing
{
get { return (double)GetValue(SpacingProperty); }
set { SetValue(SpacingProperty, value); }
}
private void OnSizeChanged()
{
this.ForceLayout();
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
if (WidthRequest > 0)
widthConstraint = Math.Min(widthConstraint, WidthRequest);
if (HeightRequest > 0)
heightConstraint = Math.Min(heightConstraint, HeightRequest);
double internalWidth = double.IsPositiveInfinity(widthConstraint) ? double.PositiveInfinity : Math.Max(0, widthConstraint);
double internalHeight = double.IsPositiveInfinity(heightConstraint) ? double.PositiveInfinity : Math.Max(0, heightConstraint);
return DoHorizontalMeasure(internalWidth, internalHeight);
}
private SizeRequest DoHorizontalMeasure(double widthConstraint, double heightConstraint)
{
int rowCount = 1;
double width = 0;
double height = 0;
double minWidth = 0;
double minHeight = 0;
double widthUsed = 0;
foreach (var item in Children)
{
var size = item.Measure(widthConstraint, heightConstraint);
height = Math.Max(height, size.Request.Height);
var newWidth = width + size.Request.Width + Spacing;
if (newWidth > widthConstraint)
{
rowCount++;
widthUsed = Math.Max(width, widthUsed);
width = size.Request.Width;
}
else
width = newWidth;
minHeight = Math.Max(minHeight, size.Minimum.Height);
minWidth = Math.Max(minWidth, size.Minimum.Width);
}
if (rowCount > 1)
{
width = Math.Max(width, widthUsed);
height = (height + Spacing) * rowCount - Spacing; // via MitchMilam
}
return new SizeRequest(new Size(width, height), new Size(minWidth, minHeight));
}
protected override void LayoutChildren(double x, double y, double width, double height)
{
double rowHeight = 0;
double yPos = y, xPos = x;
foreach (var child in Children.Where(c => c.IsVisible))
{
var request = child.Measure(width, height);
double childWidth = request.Request.Width;
double childHeight = request.Request.Height;
rowHeight = Math.Max(rowHeight, childHeight);
if (xPos + childWidth > width)
{
xPos = x;
yPos += rowHeight + Spacing;
rowHeight = 0;
}
var region = new Rectangle(xPos, yPos, childWidth, childHeight);
LayoutChildIntoBoundingRegion(child, region);
xPos += region.Width + Spacing;
}
}
}
}
請參閱我的帖子 。 它與你的情況類似。
只需要自定義Layout
並管理其大小和子項的安排。
我得到一個“類型本地:在xmlns clr-namespace:Myapp中找不到WrapLayout”錯誤。
將Class WrapLayout
public,將其與ListPage
分開。
我對這里如何應用數據綁定也有點困惑
我們需要在wraplayout中添加一個名為ItemSource
的BindableProperty
,並在屬性更改時添加子視圖。
Xmal位
<ContentPage.Content>
<local:WrapLayout x:Name="wrap" ItemSource="{Binding .}" Spacing="5" />
</ContentPage.Content>
代碼背后
List<string> list = new List<string> {
"11111111111111111111111",
"22222",
"333333333333333",
"4",
"55555555",
"6666666666666666666666",
"77777",
"8888888888",
"99999999999999999999999999999999"
};
this.BindingContext = list;
我們可以在WrapLayout
定義event
,當我們點擊或長按按鈕時,觸發事件。 關於長按,我們應該創建自定義渲染器來實現它。
namespace ImageWrapLayout
{
public class ButtonWithLongPressGesture : Button
{
public EventHandler LongPressHandle;
public EventHandler TapHandle;
public void HandleLongPress(object sender, EventArgs e)
{
//Handle LongPressActivated Event
LongPressHandle(sender, e);
}
public void HandleTap(object sender, EventArgs e)
{
//Handle Tap Event
TapHandle(sender, e);
}
}
public class WrapLayout : Layout<View>
{
public List<string> ItemSource
{
get { return (List<string>)GetValue(ItemSourceProperty); }
set { SetValue(ItemSourceProperty, value); }
}
public static readonly BindableProperty ItemSourceProperty =
BindableProperty.Create
(
"ItemSource",
typeof(List<string>),
typeof(WrapLayout),
propertyChanged: (bindable, oldvalue, newvalue) => ((WrapLayout)bindable).AddViews()
);
void AddViews()
{
Children.Clear();
foreach (string s in ItemSource)
{
ButtonWithLongPressGesture button = new ButtonWithLongPressGesture();
button.BackgroundColor = Color.Red;
button.Text = s;
button.TextColor = Color.Black;
Children.Add(button);
button.TapHandle += WrapLayoutTapHandle;
button.LongPressHandle = WrapLayoutLongPressHandle;
}
}
public EventHandler WrapLayoutLongPressHandle;
public EventHandler WrapLayoutTapHandle;
public static readonly BindableProperty SpacingProperty =
BindableProperty.Create
(
"Spacing",
typeof(double),
typeof(WrapLayout),
10.0,
propertyChanged: (bindable, oldvalue, newvalue) => ((WrapLayout)bindable).OnSizeChanged()
);
public double Spacing
{
get { return (double)GetValue(SpacingProperty); }
set { SetValue(SpacingProperty, value); }
}
private void OnSizeChanged()
{
this.ForceLayout();
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
if (WidthRequest > 0)
widthConstraint = Math.Min(widthConstraint, WidthRequest);
if (HeightRequest > 0)
heightConstraint = Math.Min(heightConstraint, HeightRequest);
double internalWidth = double.IsPositiveInfinity(widthConstraint) ? double.PositiveInfinity : Math.Max(0, widthConstraint);
double internalHeight = double.IsPositiveInfinity(heightConstraint) ? double.PositiveInfinity : Math.Max(0, heightConstraint);
return DoHorizontalMeasure(internalWidth, internalHeight);
}
private SizeRequest DoHorizontalMeasure(double widthConstraint, double heightConstraint)
{
int rowCount = 1;
double width = 0;
double height = 0;
double minWidth = 0;
double minHeight = 0;
double widthUsed = 0;
foreach (var item in Children)
{
var size = item.Measure(widthConstraint, heightConstraint);
height = Math.Max(height, size.Request.Height);
var newWidth = width + size.Request.Width + Spacing;
if (newWidth > widthConstraint)
{
rowCount++;
widthUsed = Math.Max(width, widthUsed);
width = size.Request.Width;
}
else
width = newWidth;
minHeight = Math.Max(minHeight, size.Minimum.Height);
minWidth = Math.Max(minWidth, size.Minimum.Width);
}
if (rowCount > 1)
{
width = Math.Max(width, widthUsed);
height = (height + Spacing) * rowCount - Spacing; // via MitchMilam
}
return new SizeRequest(new Size(width, height), new Size(minWidth, minHeight));
}
protected override void LayoutChildren(double x, double y, double width, double height)
{
double rowHeight = 0;
double yPos = y, xPos = x;
foreach (var child in Children.Where(c => c.IsVisible))
{
var request = child.Measure(width, height);
double childWidth = request.Request.Width;
double childHeight = request.Request.Height;
rowHeight = Math.Max(rowHeight, childHeight);
if (xPos + childWidth > width)
{
xPos = x;
yPos += rowHeight + Spacing;
rowHeight = 0;
}
var region = new Rectangle(xPos, yPos, childWidth, childHeight);
LayoutChildIntoBoundingRegion(child, region);
xPos += region.Width + Spacing;
}
}
}
}
[assembly: ExportRenderer(typeof(ButtonWithLongPressGesture), typeof(LongPressGestureRecognizerButtonRenderer))]
namespace ImageWrapLayout.iOS
{
class LongPressGestureRecognizerButtonRenderer : ButtonRenderer
{
ButtonWithLongPressGesture view;
public LongPressGestureRecognizerButtonRenderer()
{
this.AddGestureRecognizer(new UILongPressGestureRecognizer((longPress) => {
if (longPress.State == UIGestureRecognizerState.Began)
{
view.HandleLongPress(view, new EventArgs());
}
}));
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
view = e.NewElement as ButtonWithLongPressGesture;
//if(Control == null)
//{
UIButton but = Control as UIButton;
but.TouchUpInside += (sender, e1) => {
view.HandleTap(view, new EventArgs());
};
//}
}
}
}
inactiveList.WrapLayoutLongPressHandle += (sender, e) =>
{
};
inactiveList.WrapLayoutTapHandle += (sender, e) =>
{
};
你可以使用這個: https : //github.com/daniel-luberda/DLToolkit.Forms.Controls/tree/master/FlowListView
它與ListView使用的相同,但具有列支持
你在技術上可以做到這一點。 所有VisualElements都有一個Rotation BindableProperty,因此將旋轉設置為270。
public static readonly BindableProperty RotationProperty;
public static readonly BindableProperty RotationXProperty;
public static readonly BindableProperty RotationYProperty;
此代碼來自Visual Element Class。 另請參閱下面的示例。
<ListView x:Name="MessagesListView" Rotation="270" ItemsSource="{Binding Items}" RowHeight="40">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<!--mylayouthere-->
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.