Bug? TableView Update Data displayed

rwblinn

Well-Known Member
Licensed User
Longtime User
Hi Erel,

a tableview with two columns is defined. For a cell in the tableview a new value is assigned using:
B4X:
Sub setTableviewNewValue(tv As TableView, Row As Int, Cell As Int, newvalue As String)
    tv.SelectedRow = Row
    Dim rowcontent() As Object = tv.Items.get(Row)
    rowcontent(Cell) = newvalue
End Sub

The new value is not displayed, so the itemlist has to be refreshed. Using Sub A below works where as Sub B is not working. The difference between the two is the use of Items.Add.
The goal is to use Sub B as it provides flexibility in the number of columns in the tableview.
In Sub A these are hard coded for the two columns.

Any hint on how to get Sub B working?

B4X:
Sub refreshTableViewA(tv As TableView)
    Dim tvl As List
    tvl.Initialize
    tvl.AddAll(tv.Items)
    tv.Items.Clear
    For i = 0 To tvl.Size - 1
        Dim r() As Object = tvl.get(i)
        ' THIS WORKS
        tv.Items.add(Array As Object(r(0), r(1)))
      Next
End Sub

Sub refreshTableViewB(tv As TableView)
    Dim tvl As List
    tvl.Initialize
    tvl.AddAll(tv.Items)
    tv.Items.Clear
    For i = 0 To tvl.Size - 1
        Dim r() As Object = tvl.get(i)
        ' THIS NOT WORKING !!!
        tv.Items.Add(r)
      Next
End Sub
 

agraham

Expert
Licensed User
Longtime User
B is probably not working because you are adding the same array reference back into Items as you have obtained from it. I guess you need to add a different array object as in A. How you achieve that will depend upon what you actually want to do which is not evident in the simple code above.
 

rwblinn

Well-Known Member
Licensed User
Longtime User
Hi Agraham,

thanks for your reply.
When using Sub B the data is updated but not displayed in the table.
To check if the data has been updated use tableview_SelectedRowChanged and you see the new value is assigned.
If you use Sub A the updated data is displayed immediate.

Try above via:
B4X:
setTableviewNewValue(tableview1, 0, 1, "New Value")
refreshTableViewB(tableview1)
 

rwblinn

Well-Known Member
Licensed User
Longtime User
Hi Agraham,

understand - have build attached sample project to try out.

Appreciate your help.
 

Attachments

  • b4jtableview.zip
    1.8 KB · Views: 277

agraham

Expert
Licensed User
Longtime User
It is in fact working. the problem is that the TableView is not redrawing itself as it doesn't seem to know that anything has changed. Update it with button B, grab the bottom right corrner and resize the form to minimum in both X and Y then resize it back again You will see that the correct value is now shown as the TableView has refreshed itself.

The TableView Items property is an ObservableList that should signal the TableView when it changes. Either it does not signal any changes when you pass the same number of the same references back to it having cleared it or some deeper optimisation in TableView checks the items and ignores the signal if it doesn't appear to have changed. If you pass one less by shortening the loop For i = 0 To tvl.Size - 2 or one more by adding the last row again outside the loop, tv.Items.Add(r), you will see that it does refresh.

If you add different arrays by copying the originals then it does refresh.
B4X:
Sub refreshTableViewB(tv As TableView)
    ' Use a temporary list which holds the updated row (cells) objects as taken from the updated tableview list
    Dim tvl As List
    Dim bc As ByteConverter
    tvl.Initialize
    tvl.AddAll(tv.Items)
    ' Clear all items in the tableview list
    tv.Items.Clear
    ' And add the objects from the list to the tableview items
    For i = 0 To tvl.Size - 1
        Dim r() As Object = tvl.get(i)
        Dim s(r.Length) As Object
        bc.ArrayCopy(r, 0, s, 0, r.Length)
        tv.Items.Add(s)
      Next
End Sub
 

rwblinn

Well-Known Member
Licensed User
Longtime User
Hi Agraham,

thanks lot for your comprehensive reply - much appreciated. Good learning moment as well on how to use the ByteConverter!

Have searched to explore more about this problem. This one explains very good the handling of these kind of updates https://community.oracle.com/thread/2384342

The simplest workaround is the one already mentioned in one of the related threads by using SetColumnVisible:
B4X:
Sub setTableviewNewValue(tv As TableView, Row As Int, Col As Int, newvalue As String)
    ' Set the selected row first
    tv.SelectedRow = Row
    ' Get the selected row as object
    Dim rowcontent() As Object = tv.Items.get(Row)
    ' Set the new value in the cell
    rowcontent(Col) = newvalue
    ' Trigger to make the updated data visible in the tableview
    ' This more a trial and error solution - may be other (better?) solutions available
    tv.SetColumnVisible(Col, False)
    tv.SetColumnVisible(Col, True)
End Sub
 
Top