我目前有一个 WinForms 应用程序,在 TreeListView 中显示数据。数据是 CAN 消息,当前设置为一旦检测到新的 CAN 消息就更新树列表视图。主导航是一个选项卡控件,可在不同功能和传入 CAN 消息的处理之间切换。
从任何选项卡切换到我的树列表视图所在的选项卡时就会出现问题。每当 CAN 消息以 10 毫秒左右的间隔开始传入时,就会出现问题。树列表视图按照我的意愿进行绘制和更新,但所有其他控件根本不绘制,更不用说交互了。我使用选项卡控件打开的上一页也仍然显示,因此树列表视图被绘制在旧选项卡页上,没有绘制任何其他控件,并且旧选项卡页仍然显示,尽管是非交互式的。
我尝试这样做,以便每当您切换到包含 CAN 消息的选项卡页时,它都会停止处理 CAN 消息一小段时间,以便 UI 线程至少可以绘制其他控件,并且它确实有效。其他控件确实进行了绘制,但仍然没有交互性。我无法单击任何按钮或选择其他控件上的任何内容。
目前的设置是使用另一个后台线程来检查新消息,并在检测到消息时触发事件来处理该消息。然后数据处理在另一个线程上完成,最后将数据推送到 UI 线程来更新 UI。
几周前,我使用的是普通的ListView,然后这些错误都没有发生,直到现在当我切换到treelistview时才开始发生这种情况。
以下是消息处理中的一些代码: ` 字符串 sFullPGN = data.completePGN;
if (sTxtBoxPGNDisplay == sFullPGN)
txtBoxTxInfo.Text = getRxTooltip(ref data);
if (CAN_PGNS.Contains(sFullPGN))
{
int index = GetAdapterIndex(sFullPGN);
if (index != -1)
{
Adapters[index].UpdateAdapterData(data);
if (Adapters[index].Children != null) // Does the PGN contain any signals?
foreach(CANAdapter signal in Adapters[index].Children)
{
signal.UpdateChild(data);
}
// RefreshObject gives an error if a filter is applied, complains about index error since ObjectListView uses it own internal display list
// which is changed when a filter is applied. The All objects list's index is then taken directly instead of being adapted to the
// display list's matching showing index. This is all internal code of the ObjectListView and cannot be changed by us.
// See line btnCHfilter_click below.
//tlvCANIn.RefreshObject(Adapters[index]);
try { tlvCANIn.RefreshObject(Adapters[index]); } catch {}
}
}
else
{
CANAdapter newAdapter = new CANAdapter(sFullPGN);
CanMessageInfo newMessage = new CanMessageInfo();
newMessage = CANMessagesInfo.GetMessage(data.PGN_RBDP);
newAdapter.UpdateAdapterData(data);
if (newMessage != null)
{
newAdapter.comment = newMessage.name + " " + newMessage.comment;
if (newMessage.signals.Count > 0)
{
newAdapter.HasSPNs = true;
newAdapter.InitialiseChildren(newMessage.signals);
}
else
{
newAdapter.HasSPNs = false;
}
}
Adapters.Add(newAdapter);
CAN_PGNS.Add(sFullPGN);
}
}`
我发现的最佳解决方案是限制 UI 更新速率,但仍然处理带有计时器更新的 CAN 消息。我将所有需要更新的对象添加到列表中,并在计时器回调中使用
tlvMyTreeListView.RefreshObject(objectToRefresh)
更新该列表