在树状视图中更改节点的检查状态很慢

时间:2018-10-17 12:01:40

标签: c# winforms checkbox treeview

我在Map上有一个Form控件。地图控件包含一个图层集合,每个图层都有一个“ IsVisible”来隐藏或显示该图层。

我有一个TreeView控件,其中CheckBoxes代表每个图层,每个node都包含在一个父node下。

当我检查/取消选中节点时,我希望将相关层的IsVisible属性设置为等于节点的选中状态。

这是我目前正在做的事情:

private void LayerTreeView_AfterCheck(object sender, TreeViewEventArgs e)
{
    if (e.Node.Parent == null) //if it's a parent node, make any children nodes match its checked state
    {
        foreach (TreeNode node in e.Node.Nodes)
        {
            node.Checked = e.Node.Checked;
            Map.BeginInvoke((MethodInvoker)delegate () { Map.FindFeatureLayer(node.Name).IsVisible = node.Checked; });
        }
    }
    else //it's a child node
    {
        Map.FindFeatureLayer(e.Node.Name).IsVisible = e.Node.Checked;
    }
    Map.BeginInvoke((MethodInvoker)delegate () { Map.Refresh(); }); //culprit is here
}

问题在于,随着我拥有的图层/节点越多,延迟就越明显。在上面的代码中,最后一行包含Map.Refresh();

在调用Map.Refresh()之前,这些节点不会进行明显的更新,对于已更改其检查状态的每个节点都将调用该节点。这导致延迟。我需要立即更新节点。 Map控件的更新是否滞后并不重要,但这不应该相反。

1 个答案:

答案 0 :(得分:1)

我认为您需要重新考虑一下您的设计。我假设Map是TreeView控件?然后,您不需要使用BeginInvoke来调用其方法。所有要做的就是将呼叫推入队列并延迟操作。只要一切都在UI线程上,您就不需要这样做。

请记住,调用Refresh将导致树视图重绘整个树及其所有节点。对于每个节点更改,这都是很多工作,如果您不调用任何更改,则可能没有必要。我也不熟悉FindFeatureLayer,所以不知道它的工作效率如何。

最后,Microsoft文档具有有关在AfterCheck事件中设置Node.Checked属性的说明。

window.onload = function() {
  var startPos;
  navigator.geolocation.watchPosition(function(position) {
  startPos = position;
  document.getElementById('startLat').innerHTML = startPos.coords.latitude;
  document.getElementById('startLon').innerHTML = startPos.coords.longitude;

  var a =  { lat: 40.6, lng: -70.4 }

  var b = { lat: startPos.coords.latitude, lon: startPos.coords.longitude }


  zone = haversineDistance(a,b);
  document.getElementById('zone').innerHTML = zone;

  if(zone < 50){
    document.getElementById('inout').innerHTML = 'IN';
  }else{
    document.getElementById('inout').innerHTML = 'OUT';
  }

});
};

var atan2 = Math.atan2
var cos = Math.cos
var sin = Math.sin
var sqrt = Math.sqrt
var PI = Math.PI

// (mean) radius of Earth (meters)
var R = 6378137

function squared (x) { return x * x }
function toRad (x) { return x * PI / 180.0 }

function haversineDistance (a, b) {
var aLat = a.latitude || a.lat
var bLat = b.latitude || b.lat
var aLng = a.longitude || a.lng || a.lon
var bLng = b.longitude || b.lng || b.lon

var dLat = toRad(bLat - aLat)
var dLon = toRad(bLng - aLng)

var f = squared(sin(dLat / 2.0)) + cos(toRad(aLat)) * cos(toRad(bLat)) * squared(sin(dLon / 2.0))
var c = 2 * atan2(sqrt(f), sqrt(1 - f))

return R * c
}

所以也许这会更好?

Setting the TreeNode.Checked property from within the BeforeCheck or AfterCheck event
causes the event to be raised multiple times and can result in unexpected behavior. For
example, you might set the Checked property in the event handler when you are
recursively updating the child nodes so that the user does not have to expand and check
each one individually. To prevent the event from being raised multiple times, add logic
to your event handler that only executes your recursive code if the Action property of
the TreeViewEventArgs is not set to TreeViewAction.Unknown. For an example of how to do
this, see the Example section of the AfterCheck or BeforeCheck events.

希望有帮助,我目前无法完全测试。