Solved ListView dataChanged not updating all delegates
I have a C++ model connected to a ListView in QML. Inserting rows, removing rows, setData and data() all work just fine. My issues happens when I update the model through a means other than the view. In this particular case, I create a button outside of the view that is supposed to reset the values in the model and then notify the view to update accordingly. I have successfully reset the values in my model through a c++ slot and observed in the debugger that all items in the model are reset to initial values. I then emit the following to update the listview in QML
dataChanged(createIndex(0, 0), createIndex(rowCount(), 0));
And this works just fine if the user has not yet interacted with the view (I have editable items in my delegate). In the data() function I can observe all delegates at visible rows updating all roles. This is good. However, once a user interacts with the view (i.e. checks an edit-able item in the delegate and the model correctly updates) the dataChanged signal above no longer causes the data() function to be called on all visible delegates for all roles. In fact, it actually skips the delegates at the rows and roles that were updated from when the user interacted with the delegate. This means the edit-able items retain their edits and no longer reflect the newly reset data stored in the model. The only way to force the update to the view then has been with the signal:
But layoutChanged is an expensive operation and causes my GUI to freeze (view is updating) for a small but noticeable amount of time.
Does anyone know why the dataChanged() signal is not forcing an update on the delegates at the rows and roles the user interacted with? This seems like a major bug for QML model/view relationships.
since I cant see whole sources, I can only guess, but it seems you have to provide roles to update as well
This post is deleted!
You probably want
rowCount()-1as the upper bound, although I'm not sure if this will cause an issue.
Yes, I agree, rowCount() -1 would be correct. I changed it and retested but it does not change the behavior.
I also asked this question on stack overflow and someone was kind enough to answer it. It turns out I was losing my binding for the "checked" property to the model role because it was being overridden with a bool whenever a user clicked.
The soluation is at: