I am searching for a way to prohibit the ColumnSorterMixin from sorting while i am editing text. If a user clicks on a column name it will result in a sorting operation to take place but the cell which is in the editing progress will retain it’s value (see gif below). Can someone point me towards a solution?
I heard about the “event.Veto()” function. I don’t know if and how i can use it for my use case, though.
Just skipping (or not) the event, depending on whether you are currently editing or not, should be enough.
Also, keep in mind that the SorterMixing actually sorts your data, not your view… and by just editing a label one does not change the underlying data model: so you also need to update your model by hand - otherwise, subsequent ordering operations will not work as expected.
Now, the examples in the demo are rather convoluted, and they not deal with model/view syncronization anyways. Here is a much more simple example, covering all this. I will use a TextEditMixin to allow editing, but the same applies when you just pass the LC_EDIT_LABELS style to a regular ListCtrl.
import wx
import wx.lib.mixins.listctrl as listmix
data = {0: 'aaa', 1: 'ddd', 2: 'ggg', 3: 'jjj', 4: 'mmm'} # the model
class MyList(wx.ListCtrl, listmix.ColumnSorterMixin, listmix.TextEditMixin):
def __init__(self, *a, **k):
wx.ListCtrl.__init__(self, *a, **k)
self.InsertColumn(0, 'some data')
for key, val in data.items():
index = self.InsertItem(self.GetItemCount(), val)
self.SetItemData(index, key)
self.itemDataMap = data
listmix.ColumnSorterMixin.__init__(self, 1)
listmix.TextEditMixin.__init__(self)
self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.on_begin_edit)
self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.on_end_edit)
self.Bind(wx.EVT_LIST_COL_CLICK, self.on_col_click)
self._in_edit = False
def on_begin_edit(self, event):
self._in_edit = True
event.Allow()
def on_end_edit(self, event):
data[self.GetItemData(event.Index)] = event.GetText() # update model
self._in_edit = False
event.Allow()
def on_col_click(self, event):
if not self._in_edit: # skip only when not currently editing
event.Skip()
def GetListCtrl(self): return self
def GetItemCount(self): return len(data)
class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
MyList(self, style=wx.LC_REPORT)
app = wx.App()
MainFrame(None).Show()
app.MainLoop()