Xamarin.Forms - Force ListView layout to redraw
Asked Answered
P

6

8

I have a ListView with HasUnevenRows = true, where the content of each cell is variant to begin with, but the content can also change on the fly (through clicking of a button in the cell). When the ListView initially loads, the system must perform a calculation in order to correctly determine and draw the heights of each cell based on their content.

But when I update the content after the initial load, this same calculation is apparently not done, because the height of the cell does not change -- until I've scrolled that item out of view and then back into view.

How can I force this same calculation and redraw manually, without completely refreshing the ListView??

I tried wrapping the ListView in a Frame and calling .ForceLayout() on the frame, but no luck.

Pedropedrotti answered 24/5, 2016 at 12:46 Comment(0)
R
8

The height of the cells aren't recalculated by default because it is an expensive process. If you want to force a re-size you need to call ForceUpdateSize() on the cell.

NOTE: This does not work on older versions of Xamarin Forms. It was added in 2.0.0.0, but try updating to at least 2.2.0.31

Rook answered 26/5, 2016 at 13:19 Comment(3)
Interesting - I just tried that, but my application crashed on calling that command. I created a button inside the cell with a .Clicked event calling ForceUpdateSize().Pedropedrotti
ForceUpdateSize(), haha - just that.Pedropedrotti
So.....turns out my Xamarin.Forms version was the problem. I was on 2.1.0.6526. Once I upgraded to 2.2.0.31, it worked!!Pedropedrotti
O
5

Set your CachingStrategy="RetainElement", it's expensive, but will force an update a lot more. If your list isn't too long, you won't notice.

I've noticed that if a cell is visible, even though bound to an obserablecollection, that cell doesn't update until I scroll up then down.

Operon answered 7/7, 2019 at 1:4 Comment(2)
I used CachingStrategy="RecycleElement" and it worked.Describe
Using Maui, Listview with nested groups/elements. I also had/have the same initial refresh issue: when an item was displayed I show blank, although the expected size. Setting CachingStrategy="RecycleElement" on the ListView resolved, the item is displayed when it is first shown. It feels slower, will ahve to check that.Babble
P
3

I've had terrible luck getting native controls to redraw. The one thing that has worked for me has been in a custom renderer: ((IVisualElementController)Element).NativeSizeChanged()

Purism answered 26/5, 2016 at 1:31 Comment(1)
I tried various combinations of SizeToFit, SetNeedsDisplay and SetNeedsLayout. None worked. NativeSizeChanged did. ThanksPineda
A
0

You have to use DataBinding if you want your view to refresh automatically..

Aeonian answered 24/5, 2016 at 13:30 Comment(6)
I don't want to refresh the data, I only want to redraw the list in its current state.Pedropedrotti
Do you use a DataTemplate for your listview?Serving
Yes, I have a separate file for the DataTemplate.Pedropedrotti
I know that when you delete something from your list and your itemsource is observableCollection it works, it upgrades the view.. but i don't know if it will work for you. And i also dont know if you can have different sizes per row in a listview.Serving
I think in your datatemplate you should have something like if(condition==true) layout.Add(newLabel) else layout.remove(newLabel) to get condition value of your object you have to use databindingServing
@MrKocak - what does that have to do with dynamically changing the height? Sorry, I'm not following.Pedropedrotti
M
0
        YourListView.BeginRefresh ();
        YourListView.EndRefresh ();

But i strongly recommend not to do this.

Matroclinous answered 24/5, 2016 at 16:57 Comment(3)
I don't want to completely refresh the list, because I'm in a particular state of an item that I need to preserve.Pedropedrotti
It will not refresh it. It will just recalculate row/list heightsMatroclinous
I just tried it, but it has no effect. I added a "refresh" button with a .Clicked event that calls myListView.BeginRefresh() and myListView.EndRefresh(); No luck. In the clicked even, I even called a myListView.TranslateX = 100; to make sure it was affecting the list correctly, and it was - that worked. But BeginRefresh and EndRefresh didn't do anything.Pedropedrotti
A
0

The most simple and effective way is:

myListView.ItemsSource = null;
MyListView.ItemsSource = myObservableCollection;
Austrasia answered 8/4, 2022 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.