我正在编写一个Xamarin.Forms项目并且我有一个列表视图但是每当我显示隐藏的内容时,例如,使一个条目可见,ViewCell会重叠它下面的那个。
我有没有办法.Update()
列表视图或其他东西来刷新它并让它们全部适合。
我不希望刷新让它回到顶端。
当我展示某些东西时,Android似乎能够自动更新高度。
我尝试使用HasUnevenRows="True"
,但仍然没有修复它。
代码:
Message.xaml
<StackLayout>
<local:PostListView x:Name="MessageView" HasUnevenRows="True" IsPullToRefreshEnabled="True" Refreshing="MessageView_Refreshing" SeparatorVisibility="None" BackgroundColor="#54a0ff">
<local:PostListView.ItemTemplate>
<DataTemplate>
<local:PostViewCell>
<StackLayout>
<Frame CornerRadius="10" Padding="0" Margin="10, 10, 10, 5" BackgroundColor="White">
<StackLayout>
<StackLayout x:Name="MessageLayout" BackgroundColor="Transparent" Padding="10, 10, 15, 10">
...
<Label Text="{Binding PostReply}" FontSize="15" TextColor="Black" Margin="10, 0, 0, 10" IsVisible="{Binding ShowReply}"/>
<StackLayout Orientation="Vertical" IsVisible="{Binding ShowReplyField}" Spacing="0">
<Entry Text="{Binding ReplyText}" Placeholder="Reply..." HorizontalOptions="FillAndExpand" Margin="0, 0, 0, 5"/>
...
</StackLayout>
<StackLayout x:Name="MessageFooter" Orientation="Horizontal" IsVisible="{Binding ShowBanners}">
<StackLayout Orientation="Horizontal">
...
<Image x:Name="ReplyIcon" Source="reply_icon.png" HeightRequest="20" HorizontalOptions="StartAndExpand" IsVisible="{Binding ShowReplyButton}">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ReplyClick}" CommandParameter="{Binding .}"/>
</Image.GestureRecognizers>
</Image>
...
</StackLayout>
...
</StackLayout>
</StackLayout>
</StackLayout>
</Frame>
</StackLayout>
</local:PostViewCell>
</DataTemplate>
</local:PostListView.ItemTemplate>
</local:PostListView>
</StackLayout>
Message.cs
using Newtonsoft.Json;
using SocialNetwork.Classes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace SocialNetwork
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MessagePage : ContentPage
{
public MessagePage()
{
InitializeComponent();
LoadPage();
}
private async void LoadPage()
{
await LoadMessages();
}
private async void RefreshPage()
{
await LoadMessages();
MessageView.EndRefresh();
}
private async Task LoadMessages()
{
//*Web Request*
MessageView.ItemsSource = FormatPosts(this, Navigation, page_result);
...
}
public IList<MessageObject> FormatPosts(Page page, INavigation navigation, string json)
{
IList<MessageObject> Posts = new List<MessageObject>() { };
var messages = JsonConvert.DeserializeObject<List<Message>>(json);
foreach (var message in messages)
{
MessageObject mo = MessageObject.CreateMessage(...);
Posts.Add(mo);
}
return Posts;
}
public async void ShowOptionActions(string id, string poster_id, object message)
{
...
}
public async void ShowReportOptions(string id, string poster_id)
{
...
}
public void SubmitReplyClick(string id, object msg)
{
...
}
public async void SendReplyAsync(string id, object msg, string reply)
{
await SendReply(id, msg, reply);
}
public void ReplyCommandClick(string id, object msg)
{
MessageObject message = (MessageObject) msg;
message.ShowReplyField = message.ShowReplyField ? false : true;
//Update Cell Bounds
}
private async Task SendReply(string id, object msg, string reply)
{
MessageObject message = (MessageObject)msg;
...
message.PostReply = reply;
//Update Cell Bounds
}
public async void LikeMessageClick(string id, object message)
{
await LikeMessage(id, message);
}
private async Task LikeMessage(string id, object msg)
{
...
}
public async void DeleteMessage(string id, object msg)
{
MessageObject message = (MessageObject)msg;
message.ShowBanners = false;
message.ShowReply = false;
...
//Update Cell Bounds
}
public async Task ReportMessage(...)
{
...
}
private void MessageView_Refreshing(object sender, EventArgs e)
{
RefreshPage();
}
}
public class MessageObject : INotifyPropertyChanged
{
private Boolean showBannersValue = true;
private string replyValue = String.Empty;
private bool showReplyValue;
private bool showReplyButtonValue;
private bool showReplyFieldValue;
private Command replyCommandValue;
private Command replySubmitValue;
private string replyTextValue;
...
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private MessageObject(...)
{
...
}
public static MessageObject CreateMessage(...)
{
return new MessageObject(...);
}
public Boolean ShowBanners
{
get
{
return this.showBannersValue;
}
set
{
if (value != this.showBannersValue)
{
this.showBannersValue = value;
NotifyPropertyChanged();
}
}
}
public Boolean ShowReplyField
{
get
{
return this.showReplyFieldValue;
}
set
{
if(value != this.showReplyFieldValue)
{
this.showReplyFieldValue = value;
NotifyPropertyChanged();
}
}
}
public string PostReply
{
get
{
return this.replyValue;
}
set
{
if (value != this.replyValue)
{
this.replyValue = value;
NotifyPropertyChanged();
}
}
}
public Boolean ShowReply
{
get
{
return this.showReplyValue;
}
set
{
if(value != this.showReplyValue)
{
this.showReplyValue = value;
NotifyPropertyChanged();
}
}
}
public Boolean ShowReplyButton
{
get
{
return this.showReplyButtonValue;
}
set
{
if (value != this.showReplyButtonValue)
{
this.showReplyButtonValue = value;
NotifyPropertyChanged();
}
}
}
public string ReplyText
{
get
{
return this.replyTextValue;
}
set
{
if(value != this.replyTextValue)
{
this.replyTextValue = value;
NotifyPropertyChanged();
}
}
}
public Command ReplyClick
{
get
{
return this.replyCommandValue;
}
set
{
if (value != this.replyCommandValue)
{
this.replyCommandValue = value;
NotifyPropertyChanged();
}
}
}
...
}
}
答案 0 :(得分:1)
特别是对于iOS,根据单元格的变化,在ListView
中调整行的大小会有问题(请参阅here)。 Cell
上有一个方法ForceUpdateSize
,它应该通知ListView
单元格的大小已经更改,这会导致ListView
调整其行的大小。
答案 1 :(得分:1)
将IList<MessageObject>
方法返回的FormatPosts
保存在字段IList<MessageObject> _messages = new List<MessageObject>()
使用以下代码段随时更新ListView,包括检查设备是否在iOS上运行:
if(Device.RuntimePlatform == Device.iOS)
{
MessageView.ItemsSource = null;
MessageView.ItemsSource = _messages;
}
答案 2 :(得分:0)
哦,我面对同样的事情。 我想你只需要在listview中的某处添加:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.row='0'>
...
</Grid>
// This, in my case, makes my cell expand when it's true. Normal behavior
<Grid Grid.row='1' isVisible="{Binding Expand}">
...
</Grid>
</Grid>
另外,如果您想单独更新单元格,我使用CustomObservableCollection:
public class CustomObservableCollection<T> : ObservableCollection<T>
{
public CustomObservableCollection() { }
public CustomObservableCollection(IEnumerable<T> items) : this()
{
foreach(var item in items)
this.Add(item);
}
public void ReportItemChange(T item)
{
NotifyCollectionChangedEventArgs args =
new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Replace,
item,
item,
IndexOf(item));
OnCollectionChanged(args);
}
}
使用Custom ListView执行ItemClickCommand:
public class CustomListView : ListView
{
#pragma warning disable 618
public static BindableProperty ItemClickCommandProperty = BindableProperty.Create<CustomListView, ICommand>(x => x.ItemClickCommand, null);
#pragma warning restore 618
public CustomListView(ListViewCachingStrategy cachingStrategy = ListViewCachingStrategy.RetainElement) :
base(cachingStrategy)
{
this.ItemTapped += this.OnItemTapped;
}
public ICommand ItemClickCommand
{
get { return (ICommand)this.GetValue(ItemClickCommandProperty); }
set { this.SetValue(ItemClickCommandProperty, value); }
}
private void OnItemTapped(object sender, ItemTappedEventArgs e)
{
if(e.Item != null && this.ItemClickCommand != null && this.ItemClickCommand.CanExecute(e.Item))
{
this.ItemClickCommand.Execute(e.Item);
this.SelectedItem = null;
}
}
}
然后在xaml:
...
...
<Customs:CustomListView
HasUnevenRows="true"
ItemsSource="{Binding PersonList}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding DoRefreshCommand}"
ItemClickCommand="{Binding ItemClickCommand}">
...
...
</Customs:CustomListView>
最后:
public Command<Person> ItemClickCommand { get; set; }
...
ItemClickCommand = new Command<Person>(SelectionExecute);
...
private void SelectionExecute(Person arg)
{
arg.Expand = !arg.Expand;
foreach(var item in PersonList)
{
if(item.Key == arg.Id)// you will change this probably
item.ReportItemChange(arg);
}
}
希望它有所帮助:)