当前位置: 代码迷 >> 综合 >> AutoCAD.Net开发问题之:层表事件的响应(续)
  详细解决方案

AutoCAD.Net开发问题之:层表事件的响应(续)

热度:18   发布时间:2023-12-22 07:38:45.0

之前在 AutoCAD.Net开发问题之:层表事件的响应 中,没找到直接响应层表的事件,就用了 Dababase 的 Object 相关事件来替代。在测试过程中发现监听图层变化的目的倒是达到了,但会严重影响编辑操作:绘图时,任何一个简单的操作都会触发大量事件,每次事件都涉及拆箱处理,一想到每个简单操作后台都如此"沉重",强迫症不能忍。

几乎用度娘找遍了所有相关关键词,未果,最后还是谷歌给力,网上找到一篇完美解决方案:
Finding out about changes to AutoCAD layers via the Bindable Object Layer using .NET
其实也没啥可说的,关键代码就一行:

Application.UIBindings.Collections.Layers

应该是通过系统的数据绑定获取相关信息,这东西知道就很简单,直接上代码:

	using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Runtime;using Autodesk.AutoCAD.Windows.Data;using System.Collections.Specialized;using System.Collections.Generic;using System.ComponentModel;public class BolInfo{
    private static List<string> _layerNames = null;[CommandMethod("LAYMODS")]public static void GetNotifiedOnLayerChange(){
    // Get our layer list and extract the initial layer namesvar layers = Application.UIBindings.Collections.Layers;UpdateStoredLayerNames();// Attach event handlers to the layer list...// Find out when items are added or removed from the collectionlayers.CollectionChanged += (s, e) =>{
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;ed.WriteMessage("\nCollection changed: {0}", e.Action);if (e.Action == NotifyCollectionChangedAction.Add && e.NewStartingIndex == -1){
    // What happens for commands that create >1 layers?var newLays = Application.UIBindings.Collections.Layers;ed.WriteMessage("\nNew item: \"{0}\"", GetItemValue(newLays[newLays.Count - 1]));}else if (e.Action == NotifyCollectionChangedAction.Remove){
    ed.WriteMessage("\nRemoved item: \"{0}\"", _layerNames[e.OldStartingIndex]);}// As we can't access data in e.NewItems or e.OldItems// (they contain NewDataItem objects - a class that isn't exposed) get the collection again and list ited.WriteMessage("\nUpdated collection: ");foreach (var item in Application.UIBindings.Collections.Layers){
    ed.WriteMessage(" \"{0}\"", GetItemValue(item));}UpdateStoredLayerNames();};// Find out when items have been changed in the collection (although not what specifically has changed)layers.ItemsChanged += (s, e) =>{
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;ed.WriteMessage("\nItem(s) changed.");UpdateStoredLayerNames();};// Find out when properties of the collection (typically the Count, for instance) have changedlayers.PropertyChanged += (s, e) =>{
    Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;ed.WriteMessage("\nCollection property changed: {0}", e.PropertyName);};}// Store a cache of the layer namesprivate static void UpdateStoredLayerNames(){
    var layers = Application.UIBindings.Collections.Layers;_layerNames = new List<string>(layers.Count);foreach (var layer in layers){
    _layerNames.Add(GetItemValue(layer));}}// Extract the name of an item from the item descriptorprivate static string GetItemValue(ICustomTypeDescriptor item){
    return (string) item.GetProperties()["Name"].GetValue(item);}}

在此对作者 Kean Walmsley 表示感谢!相信不少同学看过他的文章,也有不少大大翻译整理,感谢感谢,努力迈进。


20191126更新:

好吧,这个方法也并不完美,Kean 提到的 ItemsChanged 不能捕捉具体哪个图层发生变化算是问题之一,不过不算主要问题。

主要问题是通知滞后性,UIBindings 的方式对常规操作完全可以胜任,但对于高频操作可能出问题。通过代码添加多个图层暂且不提,测试在系统自带的图层管理器连续新建图层,会发现间或有事件没被捕捉到。发现这个问题后又回去看原文,看有没解决办法,结果发现 Kean 的测试也有同样问题( ╯□╰ )。

下面是 Kean 测试的效果,中间有个小问题(不晓得ta发现没)

Command: LAYMODS
Command: LAYER
Command:
Command:
Collection changed: Add
New item: “Layer1”
Updated collection: “0” “Layer1”
Collection property changed: Count
Command:
Collection changed: Add
New item: “Layer2”
Updated collection: “0” “Layer1” “Layer2”
Collection property changed: Count
Command:
Collection changed: Add
New item: “Layer3”
Updated collection: “0” “Layer1” “Layer2” “Layer3”
Collection property changed: Count
Command:
Collection changed: Add
New item: “Layer4”
Updated collection: “0” “Layer1” “Layer2” “Layer3” “Layer4”
Collection property changed: Count
Command:
Collection changed: Add
New item: “Layer5”
Updated collection: “0” “Layer1” “Layer2” “Layer3” “Layer4” “Layer5”
Collection property changed: Count
Command:
Command:
Collection changed: Add
New item: “Layer7”
Updated collection: “0” “Layer1” “Layer2” “Layer3” “Layer4” “Layer5” “Layer6” “Layer7”
Collection property changed: Count
Command:
Collection changed: Add
New item: “Layer8”
Updated collection: “0” “Layer1” “Layer2” “Layer3” “Layer4” “Layer5” “Layer6” “Layer7” “Layer8”
Collection property changed: Count

细看上面 Layer5 到 Layer7,中间缺了个 Layer6 ,应该就是连续新建图层,事件通知来不及造成的,使用时候要注意。