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.

jbyrd
  • 5,287
  • 7
  • 52
  • 86

6 Answers6

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

Christine
  • 562
  • 3
  • 19
  • 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()`. – jbyrd May 26 '16 at 15:05
  • 1
    `ForceUpdateSize()`, haha - just that. – jbyrd May 26 '16 at 19:20
  • 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!! – jbyrd May 26 '16 at 19:42
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.

Ian Vink
  • 66,960
  • 104
  • 341
  • 555
  • 1
    I used CachingStrategy="RecycleElement" and it worked. – Scott Nimrod Jul 18 '19 at 20:58
  • 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. – balintn Feb 11 '23 at 21:15
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()

joe
  • 1,125
  • 9
  • 18
0

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

Mr.Koçak
  • 313
  • 4
  • 9
  • I don't want to refresh the data, I only want to redraw the list in its current state. – jbyrd May 24 '16 at 20:33
  • Do you use a DataTemplate for your listview? – Mr.Koçak May 25 '16 at 07:51
  • Yes, I have a separate file for the DataTemplate. – jbyrd May 25 '16 at 14:50
  • 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. – Mr.Koçak May 26 '16 at 08:06
  • 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 databinding – Mr.Koçak May 26 '16 at 08:17
  • 1
    @MrKocak - what does that have to do with dynamically changing the height? Sorry, I'm not following. – jbyrd May 26 '16 at 13:47
0
        YourListView.BeginRefresh ();
        YourListView.EndRefresh ();

But i strongly recommend not to do this.

Artem Zelinskiy
  • 2,201
  • 16
  • 19
  • I don't want to completely refresh the list, because I'm in a particular state of an item that I need to preserve. – jbyrd May 24 '16 at 20:32
  • It will not refresh it. It will just recalculate row/list heights – Artem Zelinskiy May 25 '16 at 06:20
  • 1
    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. – jbyrd May 25 '16 at 15:21
0

The most simple and effective way is:

myListView.ItemsSource = null;
MyListView.ItemsSource = myObservableCollection;
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103