diff --git "a/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.assets/2HJE@WH1`PPUBOH2ZFL$BT.png" "b/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.assets/2HJE@WH1`PPUBOH2ZFL$BT.png" deleted file mode 100644 index 459930b8d54d075d94b4d06e960fbbc7edbdd17b..0000000000000000000000000000000000000000 Binary files "a/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.assets/2HJE@WH1`PPUBOH2ZFL$BT.png" and /dev/null differ diff --git "a/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.md" "b/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.md" deleted file mode 100644 index 26f09091f8e0321b4418e199aaa47792282ff1b5..0000000000000000000000000000000000000000 --- "a/docs/0x01\344\273\243\347\240\201\350\247\204\350\214\203.md" +++ /dev/null @@ -1,132 +0,0 @@ -# IFox工程规范 - -## 代码规范 - -### 0x01 分离逻辑代码和业务代码 - -Good: - -```c# -foreach (xx in yyy) - if (xx == "a") - { - 业务(); - break; - } -``` - -Bad: - -```c# -bool flag = false; -foreach (xx in yyy) - if (xx == "a") - { - 业务(); - flag = true; - break; - } -if(!flag) - 其他业务(); -``` - -Good: - -```c# -bool flag = false; -foreach (xx in yyy) - if (xx == "a") - { - flag = true; - break; - } -if(!flag) - 其他业务(); -else - 业务(); -``` - -主要原因是统一业务在判断分支上,能够更清晰分离逻辑代码和业务代码. - -### 0x02 分离逻辑代码和业务代码 - -![img](0x01%E4%BB%A3%E7%A0%81%E8%A7%84%E8%8C%83.assets/2HJE@WH1%60PPUBOH2ZFL$BT.png) - -上述代码中出现了这种情形: for {业务1,业务2,业务1,业务2....} - -如果有这样的逻辑,那么我们看代码的时候总是认为业务2某种条件必须要跟着业务1. - -优化代码的人一看:这代码就不能动了!! 相信我,若干年后的你就是这个优化代码的人. - -所以这样的情况下,我们采用的是用个`List`收集拆离(业务)的id,然后在最后进行循环拆离(业务). - -### 0x03 .editorconfig 配置要求 - -c#的代码风格是两个大括号隔行 - -```c# -if() -{ - ... -} -``` - -但是,由于vs没有制作好的原因,导致`委托箭头`代码格式化总是会出现格式化错误. -所以我们推荐用 .editorconfig 文件约束这个`委托箭头` - -在.edirorconfig文件上面增加此句: - -``` -csharp_style_var_elsewhere = false -``` - -没有这个文件的话,请使用如下步骤: - -```mermaid -graph LR -vs --> 选项 --> 文本编辑器 --> c# -->代码样式,展开它 --> 格式设置 --> 新行 --> 右页,大括号的新行选项 --> 将lambda表达式的左括号置于新行,取消掉勾勾 -``` - -保存为 .editorconfig 文件,并放在.sln旁边,加入git管理: - -```mermaid -graph LR -vs --> 选项 --> 文本编辑器 --> c# -->代码样式 --> 右页,基于设置生成.editorconfig文件 --> 保存到工程中 -``` - -以后每次打开工程vs会自动识别这个 .editorconfig 文件,而不会用你电脑默认设置的. - -### 0x04 所有的注释符号//后面加空格 - -利用此正则替换: - -``` -(? - { - ltt.AsciiDescription = "虚线"; - ltt.PatternLength = 0.95; //线型的总长度 - ltt.NumDashes = 4; //组成线型的笔画数目 - ltt.SetDashLengthAt(0, 0.5); //0.5个单位的划线 - ltt.SetDashLengthAt(1, -0.25); //0.25个单位的空格 - ltt.SetDashLengthAt(2, 0); // 一个点 - ltt.SetDashLengthAt(3, -0.25); //0.25个单位的空格 - }); - // 这段代码同时演示了 ifoxcad 类库关于符号表的public ObjectId Add(string name, Action action)这个函数的用法。 - // 或者直接调用: - tr.LinetypeTable.Add("hah", "虚线",0.95,new double[]{0.5,-0.25,0,-0.25}); - // 获取线型表 - tr.LinetypeTable["hah"]; - ``` - - **其他符号表的操作类同。如果类库没有提供的Add函数的重载,那么Action委托可以完成你想完成的所有事情。** - -## 基础属性操作 - -事务管理器类提供了`Document`、 `Editor` 、`Database`三个属性来在事务内部处理相关事项。 - -同时还提供了关于字典的相关属性。 - -## 对象获取操作 - -提供了1个泛型 `GetObject`函数的重载来根据ObjectId来获取到对象。 - -## 字典操作(未完待续) - -- 扩展字典 - - `SetXRecord` 保存扩展数据到字典 - - `GetXRecord ` 获取扩展数据 - -- 对象字典 - - `SetToDictionary` 保存数据到字典 - - `GetFromDictionary` 从字典获取数据 - - `GetSubDictionary` 获取子对象字典 diff --git a/docs/SelectionFilter.md b/docs/SelectionFilter.md deleted file mode 100644 index bc31b55c3c7d630bd238e99c76ba8e830b4210fe..0000000000000000000000000000000000000000 --- a/docs/SelectionFilter.md +++ /dev/null @@ -1,208 +0,0 @@ -# 选择集过滤器用法 - -## 选择集过滤器简介 - -桌子提供了选择集过滤器是为了更精确的选择对象。可以通过使用选择过滤器来限制哪些对象被选中并添加到选择集,选择过滤器列表通过属性或类型过滤所选对象。 - -在桌子的 .net api 中:选择过滤器由一对 TypedValue 参数构成。TypedValue 的第一个参数表明过滤器的类型(例如对象),第二个参数为要过滤的值(例如圆)。过滤器类型是一个 DXF 组码,用来指定使用哪种过滤器。 - -默认的使用桌子api来创建选择集(带过滤器)分三步: - -1. 创建一个TypedValue数组来定义过滤器条件 - - ```csharp - TypedValue[] acTypValAr = new TypedValue[1]; // 创建数组 - acTypValAr.SetValue(new TypedValue((int)DxfCode.Start, "CIRCLE"), 0); - // 添加一个过滤条件,例如选择圆 - - // 如果要创建多个过滤条件怎么办? - TypedValue[] acTypValAr = new TypedValue[3]; - acTypValAr.SetValue(new TypedValue((int)DxfCode.Color, 5), 0); - acTypValAr.SetValue(new TypedValue((int)DxfCode.Start, "CIRCLE"), 1); - acTypValAr.SetValue(new TypedValue((int)DxfCode.LayerName, "0"), 2); - // 实际上只要不停的往数组里添加条件就可以了 - ``` - -2. 创建SelectionFilter对象 - - ```csharp - // 将过滤器条件赋值给 SelectionFilter 对象 - SelectionFilter acSelFtr = new SelectionFilter(acTypValAr); - ``` - -3. 创建选择集 - - ```csharp - // 请求用户在图形区域选择对象 - PromptSelectionResult acSSPrompt; - acSSPrompt = acDocEd.GetSelection(acSelFtr); - ``` - -看起来很是简单对不对,单个条件和多个条件的过滤非常简单。当指定多个选择条件时,AutoCAD 假设所选对象必须满足每个条件。我们还可以用另外一种方式定义过滤条件。对于数值项,可以使用关系运算(比如,圆的半径必须大于等于 5.0)。对于所有项,可以使用逻辑运算(比如单行文字或多行文字)。使用 DXF 组码-4 或常量 DxfCode.Operator 表示选择过滤器中的关系预算符类型。运算符本身用字符串表示。 - -比如: - -1. 过滤半径大于等于5.0的圆 - - ```csharp - TypedValue[] acTypValAr = { - new TypedValue((int)DxfCode.Start, "CIRCLE"), - new TypedValue((int)DxfCode.Operator, ">="), - new TypedValue(40, 5) - }; - ``` - -2. 过滤单行文本或者多行文本 - - ```csharp - TypedValue[] acTypValAr = { - new TypedValue((int)DxfCode.Operator, "") - }; - ``` - -3. 更复杂的过滤条件呢?比如选择的对象为不是位于0图层的直线,或者位于2图层的组码10的x坐标>10,y坐标>10的非圆图元。 - - 对应的lisp代码如下: - - ```lisp - '((-4 . "") - (-4 . "not>") - (-4 . "") - (8 . "2") - (-4 . ">,>,*")(10 10 10 0) - (-4 . "and>") - (-4 . "or>")) - ``` - - 对应的c#代码: - - ```csharp - TypedValue[] acTypValAr = { - new TypedValue((int)DxfCode.Operator, ""), - new TypedValue((int)DxfCode.Operator, "not>"), - new TypedValue((int)DxfCode.Operator, ""), - new TypedValue((int)DxfCode.LayerName, "2"), - new TypedValue((int)DxfCode.Operator, ">,>,*"), - new TypedValue(10, new Point3d(10,10,0)), - new TypedValue((int)DxfCode.Operator, "and>"), - new TypedValue((int)DxfCode.Operator, "or>") - }; - ``` - - 这个过滤器是不是看起来很乱,一眼看去根本不知道是要过滤什么,写起来也很麻烦。所以说,虽然桌子提供了api,但是简单的过滤条件很好用,但是复杂的过滤条件就很复杂了。 - - 因此IFox内裤提供了关于选择集过滤器的辅助类来帮助用户用更简单的方式来创建选择集的过滤器。 - -## 内裤过滤器对象与cad过滤器对应关系 - -IFoxCad内裤对于DxfCode.Operator枚举构建了一些辅助函数来表达关系运算和逻辑运算;提供了dxf函数来表达组码。其对应的关系如下表: - -| 内裤过滤器对象、函数 | cad .net api 过滤器对象、函数、枚举 | 备注 | -|:----------:|:------------------------:|:-------------------:| -| OpFilter | SelectionFilter | 隐式转换 | -| OpOr | "" | | -| Op.Or | "" | | -| OpAnd | "" | | -| Op.And | "" | | -| OpNot | "" | | -| OpXor | "" | | -| OpEqual | 相等运算 | | -| OpComp | 比较运算符 | | -| Dxf() | 组码函数 | 仅用于过滤器中,不是组码操作函数 | -| ! | "" | | -| == | "=" | | -| != | "!=" | | -| > | ">" | | -| < | "<" | | -| >= | ">=" 或 ">,>,*" | ">,>,*"用于跟point3d比较 | -| <= | "<=" 或 "<,<,*" | "<,<,*"用于跟point3d比较 | -| & | "" | | -| ^ | "" | | -| \| | "" | | - -## 具体用法 - -IFoxCad内裤提供了三种方式来构建过滤器,其实大同小异,就是写法不一样,用户可以根据自己的喜好来选择。 - -- 第一种 - - ```csharp - var fd = - new OpOr //定义一个 (-4 . "") - { - !new OpAnd //定义(-4 . "")(-4 . "not>") - { - { 0, "line" }, //{组码,组码值} - { 8, "0" }, //{组码,组码值} - }, - new OpAnd //定义(-4 . "") - { - !new OpEqual(0, "circle"), //定义(-4 . "") - { 8, "2" }, //{组码,组码值} - { 10, new Point3d(10,10,0), ">,>,*" } //(-4 . ">,>,*")(10 10 10 0) - }, - }; - editor.SelectAll(fd); //这里直接传入fd就可以了 - ``` - - 以上代码的含义为:选择的对象为不是位于0图层的直线,或者位于2图层的组码10的x坐标>10,y坐标>10的非圆图元。其同含义的lisp代码如下: - - ```lisp - '((-4 . "") - (-4 . "not>") - (-4 . "") - (8 . "2") - (-4 . ">,>,*")(10 10 10 0) - (-4 . "and>") - (-4 . "or>")) - ``` - -- 第二种 - - ```csharp - var p = new Point3d(10, 10, 0); - var f = OpFilter.Bulid(e => - !(e.Dxf(0) == "line" & e.Dxf(8) == "0") - | e.Dxf(0) != "circle" - & e.Dxf(8) == "2" - & e.Dxf(10) >= p); - editor.SelectAll(f); //这里直接传入f就可以了 - ``` - - 代码含义如第一种。 - -- 第三种 - - ```csharp - var f2 = OpFilter.Bulid( - e =>e.Or( - !e.And(e.Dxf(0) == "line", e.Dxf(8) == "0"), - e.And(e.Dxf(0) != "circle", e.Dxf(8) == "2", e.Dxf(10) >= new Point3d(10, 10, 0))) - ); - editor.SelectAll(f2); //这里直接传入f2就可以了 - ``` - - 代码含义如第一种,第三种和第二种的写法非常像,区别就是关于 and 、or 、not 等运算符,一个是采用c#的语法,一个是采用定义的函数。and 与&等价,or与|等价,not 与!等价。 \ No newline at end of file diff --git a/docs/SymbolTable.md b/docs/SymbolTable.md deleted file mode 100644 index a5144baea56a722688da09f929cfd04e9d243ed7..0000000000000000000000000000000000000000 --- a/docs/SymbolTable.md +++ /dev/null @@ -1,146 +0,0 @@ -# 符号表用法 - -每个图形文件都包含有9个固定的符号表。不能往数据库里添加新的符号表。如图层表(LayerTable),其中包含图层表记录,还有块表(BlockTable),其中包含块表记录等。所有的图形实体(线、圆、弧等等)都属于一个块表记录。缺省情况下,任何图形文件都包含为模型空间和图纸空间预定义的块表记录。每个符号表都有对应的符号表记录,可以理解为符号表是一个集合,而符号表记录是这个集合的元素。CAD的符号表和符号表记录的对应关系如下: - -| 名称 | 符号表 | 符号表记录 | -|:-------:|:--------------:|:--------------------:| -| 块表 | BlockTable | BlockTableRecord | -| 标注样式表 | DimStyleTable | DimStyleTableRecord | -| 图层表 | LayerTable | LayerTableRecord | -| 线型表 | LinetypeTable | LinetypeTableRecord | -| 注册应用程序表 | RegAppTable | RegAppTableRecord | -| 字体样式表 | TextStyleTable | TextStyleTableRecord | -| 坐标系表 | UcsTable | UcsTableRecord | -| 视口表 | ViewportTable | ViewportTableRecord | -| 视图表 | ViewTable | ViewTableRecord | - -那么如何来操作这些符号表呢?下面是一个新建图层的例子: - -```csharp -Document acDoc = Application.DocumentManager.MdiActiveDocument; -Database acCurDb = acDoc.Database; -using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) -{ - // 返回当前数据库的图层表 - LayerTable acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,OpenMode.ForRead) as LayerTable; - // 检查图层表里是否有图层 MyLayer - if (acLyrTbl.Has("MyLayer") != true) - { - // 以写模式打开图层表 - acLyrTbl.UpgradeOpen(); - // 新创建一个图层表记录,并命名为”MyLayer” - LayerTableRecord acLyrTblRec = new LayerTableRecord(); - acLyrTblRec.Name = "MyLayer"; - // 添加新的图层表记录到图层表,添加事务 - acLyrTbl.Add(acLyrTblRec); - acTrans.AddNewlyCreatedDBObject(acLyrTblRec, true); - //提交修改 - acTrans.Commit(); - } - // 关闭事务,回收内存; -} -``` - -上面的例子用了20多行的代码来完成一个很简单的功能,这就是AutoCAD提供的api太过于基础,没有进行进一步的封装造成。那么如果我们单独为图层表封装一个函数来处理图层表,其他的8个符号表也要同样的各自封装函数,这样看起来没什么问题,但是对于代码的复用却没有很好的考虑进去。仔细思考一下,其实对于符号来说无非就是增删改三个主要的操作等,对于符号表记录来说无非就是一些属性的操作,增加实体的操作等。那么有没有一种办法可以统一管理9个符号表呢?其实AutoCAD提供了9个符号表和符号表记录的抽象基类,SymbolTable和SymbolTableRecord,但是这两个类提供的功能又很简单,只有寥寥几个函数和属性,完全不能满足我们的需求。因此ifoxcad内裤提供了符号表类来封装9个符号表的大部分功能。那么用内裤来完成上述的操作是什么样子的呢?见下面的例子: - -```csharp -// 以下代码采用最新的c#版本语法 -using var tr = new DBTrans(); // 打开事务 -var layertable = tr.LayerTable.Add("MyLayer"); //添加图层 -``` - -同样的功能我们只需要两行就可以搞定了。那么有同学会问了,我同样单独对每个符号表的封装一样可以达到这个效果?是的,确实可以达到一样的效果,但是我只封装了一次,只是针对符号表的差异部分做了一些增量的处理,其他的代码都是复用的,而你要写9次。 - -言归正传,通过上述的例子,我们会发现几个现象: - -1. 符号表的操作是在事务内。 -2. 符号表成了事务的属性 -3. 添加符号表记录到符号表调用Add函数就可以了(其实提供了好多的重载,来完成不同的细粒度的操作)。 - -符号表的操作都在事务内,这样由事务统一管理符号表的变动,减少出错的可能。 - -符号表作为事务的属性,那么获取符号表记录就变成了属性的索引值。`var layertable = tr.LayerTable["MyLayer"];` - -不管是什么符号表,都是一个Add函数搞定添加操作。 - -而删除就是:`tr.LayerTable.Remove("1");` *注意,这里的关于删除图层的操作需要调用Delete函数* - -看,我教会了你操作图层表,那么其他的8个表你都会了,都是一样的操作。 - -## 块表添加图元 - -一般的情况下,添加图元的操作都是要在事务里完成。目前大部分的添加图元的自定义函数都是DataBase或Editor对象的扩展函数。但是实际上添加图元的本质是读写图形数据库,具体的手段是对块表里的块表记录的读写。而实际的操作其实都是在事务里完成,所以符合cad操作规则的写法其实应该是事务作为一系列操作的主体来进行。因此ifoxcad内裤的封装思路为:扩展块表记录的函数,在事务管理器类里通过属性调用AddEntity函数来添加图元。 - -对于这个添加图元的操作,一共分为如下几步: - -1. 创建图元对象,可以在事务外创建,也可以在事务内创建。 -2. 打开要添加图元的块表记录,在事务内打开。 -3. 添加图元到块表记录 - -下面看示例: - -- 添加图元到当前空间 - - ```csharp - // 以下代码采用最新的c#版本语法 - using var tr = new DBTrans(); //开启事务管理器 - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); //定义一个直线 - tr.CurrentSpace.AddEntity(line1); // 将直线添加到当前绘图空间的块表记录 - ``` - -- 添加图元到模型/图纸空间 - - ```csharp - // 以下代码采用最新的c#版本语法 - using var tr = new DBTrans(); //开启事务管理器 - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); //定义一个直线 - tr.CurrentSpace.AddEntity(line1); // 将直线添加到当前绘图空间的块表记录 - tr.ModelSpace.AddEntity(line1); // 将直线添加到当前模型空间的块表记录 - tr.PaperSpace.AddEntity(line1); // 将直线添加到当前图纸空间的块表记录 - ``` - -- 添加图元到块表 - - ```csharp - // 以下代码采用最新的c#版本语法 - using var tr = new DBTrans(); //开启事务管理器 - var line1 = new Line(new Point3d(0, 0, 0), new Point3d(1, 1, 0)); //定义一个直线 - var btr = tr.BlockTable.Add("test"); //定义一个块表记录 - btr.AddEntity(line1); // 将直线添加到当前控件的块表记录 - ``` - - 那么大家猜一猜,这个添加到块表是实现了一种什么样的功能。 - -- 块表 - - 块表这里需要特殊的说明一下: - - 比如说添加一个块,用如下代码: - - `tr.BlockTable.Add(blockName, btr => btr.AddEntity(ents));` - - 这里的blockName就是块名,ents就是图元列表。这种方式虽然可以更细粒度的控制定义的块。 - - 插入块参照,比如: - - `tr.InsertBlock(point,objectid); // 用于插入块参照,提供了重载函数来满足不同的需求` - -- 其他函数的介绍 - - `tr.BlockTable.GetRecord()` 函数,可以获取到块表的块表记录,同理层表等符号表也有同样的函数。 - - `tr.BlockTable.GetRecordFrom()` 函数,可以从文件拷贝块表记录,同理层表等符号表也有同样的函数。 - - `tr.BlockTable.GetBlockFrom()` 函数,从文件拷贝块定义,同理层表等符号表也有同样用途的函数。 - -- 添加图元函数 - - 内裤提供了一些便利的添加图元函数,可以不用先定义一个entity对象,然后添加到块表记录。 - - ```csharp - using var tr = new DBTrans(); - tr.CurrentSpace.AddLine(new Point3d(0,0,0),new Point3d(1,1,0)); - tr.CurrentSpace.AddCircle(new Point3d(0,0,0),10); - ``` - - diff --git a/docs/WPF.md b/docs/WPF.md deleted file mode 100644 index 73f4f1116be4ef9cff68117b0f2fd86acf32d382..0000000000000000000000000000000000000000 --- a/docs/WPF.md +++ /dev/null @@ -1,353 +0,0 @@ - - -# WPF支持 - -在项目文件里将``替换为``。 - -在``标签里的`NET45`下面添加: -```xml -true -true -``` - -最后的项目文件如下: - -```xml - - - net47 - - true - - true - - - -``` - -# mvvm模式支持 - -## 一、简单mvvm的实现 - -使用WPF的最佳实践就是采用mvvm模式,为了支持在cad插件里使用mvvm,ifoxcad内裤定义了两个简单基类来完成属性通知和命令定义。当然这是一种及其简单的mvvm模式的支持,你还要自己手动来写大部分的代码来实现完整的mvvm模式。 - -要实现mvvm模式,要新建一个XXXView文件,一个XXXViewModel文件。我们应该采用一种通用的命名约定,即所有的gui显示都有XXXView来完成,而所有的业务逻辑都由XXXViewModel来完成。下面以一个具体的示例来说明怎么在cad的插件里使用mvvm模式。 - -1. 将我们上一节建立的MyWindow1文件改名为MyWindowView,然后将涉及到的类名也全部更改为MyWindowView。 - -2. 然后将MyWindowView.xaml文件的内容改为: - -```xaml - - - - - - - - -``` - -就是添加了一个文本框,一个按钮。 - -3. 新建MyWindowViewModel.cs文件,内容如下: - -```c# -using IFoxCad.WPF; // 这里引入IFoxCad.WPF命名空间,以便可以使用ViewModelBase和RelayCommand - -namespace Test -{ - class MyWindowViewModel : ViewModelBase - { - // 定义一个属性用于在文本框里显示 - private string _name; - public string Name - { - get { return _name; } - set - { - Set(ref _name, value); - } - } - - // 定义一个命令用于按钮的点击动作 - private RelayCommand clickCommand; - public RelayCommand ClickCommand - { - get - { - if (clickCommand == null) - { - clickCommand = new RelayCommand( - execute => Name = "hello " + Name, // 定义要执行的行为 - can => {return !string.IsNullOrEmpty(Name);}); // 定义命令是否可用 - } - return clickCommand; - } - } - // 初始化Name属性为 World - public MyWindowViewModel() - { - Name = "World"; - } - } -} - -``` - -这里需要注意的是,定义的属性是为了将属性绑定到文本框的Text属性上,这个叫做数据绑定。然后wpf里对于我们winform里的事件其实采用的更高级一些的命令来完成。本示例,定义的命令也是一个属性,这个属性返回一个RelayCommand对象的实例,这是实例的初始化函数包括两个部分,一个是要执行的动作,第二个是确定什么条件下按钮是不可用的,这个是通过命令是否可用来完成,是要命令是不能执行的,wpf会自动将控件切换为不可用状态,使其不可点击。 - -4. 现在回过头来对在xaml里将刚刚的viewmodel里定义的属性和命令绑定到控件上。 - -```xaml - - -``` - -将这两行代码替换一下。然后在后台代码里(MyWindowView.xaml.cs)添加一行代码将viewmodel绑定到view上。 - -```c# -public MyWindowView() -{ - InitializeComponent(); - DataContext = new MyWindowViewModel(); //这里将一个viewmodel的实例绑定到view的DataContext属性上。 -} -``` - -5. 至此,一个简单的wpf的mvvm模式的代码就完成了,下面的代码演示了怎么在cad里显示这个wpf窗体。 - -```c# -[CommandMethod("test")] -public void Test() -{ - var test = new MyWindowView(); - Application.ShowModalWindow(test); -} -``` - -6. 最后,这个窗体的效果是,当你点击按钮时,文本框的文字前面会加上hello。当你将文本框的文字全部删除后,按钮会变成不可用状态。如果你在试验的时候没有这个效果,这是cad的延迟导致的。多删除几次试几次后就会如期运行。 - -## 二、mvvm中的事件处理 - -在WPF里,并不是所有的控件都提供了commad属性用于绑定命令,所以还是需要进行控件的事件处理的,比如窗口的Loaded事件,鼠标事件,键盘事件等。关于WPF的事件处理,IFoxCad内裤提供了两种方式进行处理,一种就是利用 **Microsoft.Xaml.Behaviors.dll** 这个类库,利用了 **i:Interaction.Triggers** 标签在xaml文件里将命令绑定到事件上,这种方式是网上比较常见的一种方式;第二种是自定义了一个xaml标签 **eb:EventBinding** ,利用这个标签将命令绑定到事件上。两种方式实现的效果是一样的,但是 **eb:EventBinding** 标签绑定的方式的代码量要小一些。 - -下面就两种方式实现同一种事件处理的效果提供了两种方式的代码示例作为说明。由于两种方式的差异主要在xaml文件里,ViewModel的代码是一样的。因此主要讲述两种xaml的差异部分,ViewModel的代码直接贴在下面不做讲解。 - -```c# -public class TestViewModel : ViewModelBase -{ - - private bool _IsReceiveMouseMove = true; - public bool IsReceiveMouseMove - { - get { return _IsReceiveMouseMove; } - set - { - Set(ref _IsReceiveMouseMove, value); - } - } - - private string _tipText; - public string TipText - { - get { return _tipText; } - set - { - Set(ref _tipText, value); - } - } - - - - private RelayCommand loadedCommand; - - public RelayCommand LoadedCommand - { - get - { - if (loadedCommand == null) - { - loadedCommand = new RelayCommand(execute => MessageBox.Show("程序加载完毕!")); - - } - return loadedCommand; - } - - } - - private RelayCommand mouseMoveCommand; - public RelayCommand MouseMoveCommand - { - get - { - if (mouseMoveCommand == null) - { - mouseMoveCommand = - new RelayCommand( - e => - { - var point = e.GetPosition(e.Device.Target); - var left = "左键放开"; - var mid = "中键放开"; - var right = "右键放开"; - - if (e.LeftButton == MouseButtonState.Pressed) - { - left = "左键放下"; - } - if (e.MiddleButton == MouseButtonState.Pressed) - { - mid = "中键放下"; - } - if (e.RightButton == MouseButtonState.Pressed) - { - right = "右键放下"; - } - - TipText = $"当前鼠标位置 X:{point.X} Y:{point.Y} 当前鼠标状态:{left} {mid} {right}."; - }, - o => IsReceiveMouseMove); - } - return mouseMoveCommand; - } - } -} -``` - -### 2.1 自定义标签的方式 - -首先是在xaml里引入命名空间。 - -`xmlns:eb="clr-namespace:IFoxCAD.WPF;assembly=IFoxCAD.WPF"` - -然后 - -`Loaded="{eb:EventBinding Command=LoadedCommand}"` - -`MouseMove="{eb:EventBinding Command=MouseMoveCommand,CommandParameter=$e}"` 这里要注意的是显式的传入了鼠标移动事件的参数。 - -注意命令参数部分,如果这个事件是带参数的,或者说这个命令是带参数的,要传入参数。 - -关于命令及命令参数使用方式如下: - -- Command - 1. `{eb:EventBinding}` 利用简单的名字匹配来自动搜寻命令,也就是说不用指定命令名,不是很推荐。 - 2. `{eb:EventBinding Command=CommandName}` 指定命令名,建议总是使用这种方式 - -- CommandParameter - 1. `$e` (事件参数,这里特指的是事件本身带的参数,也就是你以前写事件的处理函数时候的XXXXEventArgs e这个参数) - 2. `$this` or ​`$this.Property` (view本身或者属性) - 3. `string` (要传入的字符串) - -完整的xaml代码如下: - -```xaml - - - - - -``` - -### 2.2 利用Behaviors的方式 - -首先nuget安装**Microsoft.Xaml.Behaviors.Wpf**包。 - -然后在xaml文件里,引入命名空间。 - -`xmlns:eb="clr-namespace:IFoxCad.WPF;assembly=IFoxCad"` - -`xmlns:i="http://schemas.microsoft.com/xaml/behaviors"` - -然后绑定命令到事件上: - -```xaml - - - - - - - - -``` - -细心的同学可能会发现绑定命令的地方标签是不一样的。 - -**i:InvokeCommandAction** 这个标签是由 **Microsoft.Xaml.Behaviors.Wpf** 包提供的。 - -**eb:EventCommand** 这个标签是由IFoxCad内裤提供的。 - -两者的区别就是InvokeCommandAction 是不能传入事件的参数的,所以为了处理事件参数自定义了EventCommand。就如同上面的鼠标移动事件,是有时间参数要处理的,所以用了自定义的EventCommand,虽然xaml文件里没有显式的传入这个参数。 - -虽然InvokeCommandAction这个标签的后面是可以带命令参数的,比如: - -```xaml - - - - - -``` - -但是这个命令参数是不能处理事件自带的参数的 。 - -最后是完整的xaml代码: - -```xaml - - - - - - - - - - - - - - -``` - -### 2.3 关于两种方式的选择 - -送给选择困难症的:如果可以选择自定义标签的方式,简单一些。遇到问题解决不了,就用behaviors的方式,网上的资源丰富一些,也许能找到你的答案。 - -## 三、 关于mvvm模式的建议 - -我们并不推荐严格的mvvm模式,主要原因是要引入比如message模式等方式处理类似窗口关闭,窗口间通信等问题。鉴于cad插件的界面复杂程度还没到后台事件满天飞,逻辑复杂的地步,因此后台写点事件处理,界面和后逻辑混在一起也未尝不可。 - -仅仅是建议,你爱怎样就怎样。 - diff --git a/docs/autoreg.md b/docs/autoreg.md deleted file mode 100644 index 72f377c24b7129336ebfa5a8e22f55fbc57697c5..0000000000000000000000000000000000000000 --- a/docs/autoreg.md +++ /dev/null @@ -1,62 +0,0 @@ -## 自动加载与初始化 - -### 1、简单版 - -为了将程序集的初始化和通过写注册表的方式实现自动加载统一设置,减少每次重复的工作量,类裤提供了`AutoLoad`抽象类来完成此功能,只要在需要初始化的类继承`AutoLoad`类,然后实现`Initialize()` 和 `Terminate()` 两个函数就可以了。 -特别强调的是,一个程序集里只能有一个类继承,不管是不是同一个命名空间。 - -如果要将dll的目录加入支持文件目录,请在 `Initialize` 函数中调用`AppendSupportPath(CurrentDirectory.FullName);` - -其他需要初始化执行的函数及设置都需要在 `Initialize` 函数中执行。 - -### 2、功能版 - -使用特性进行分段初始化是目前最佳选择,下面的说明已和最新版本不符,等待修正吧。 - -```csharp - using Autodesk.AutoCAD.Runtime; - using IFoxCAD.Cad; - using System; - using System.Reflection; - -/* - * 自动执行接口 - * 这里必须要实现一次这个接口,才能使用 IFoxInitialize 特性进行自动执行 - */ -public class CmdINI : AutoRegAssem -{ - // 这里可以写任何普通的函数,也可以写下面 AutoTest 类里的实现了 IFoxInitialize 特性的初始化函数 - // 继承AutoRegAssem的主要作用是写注册表用来自动加载dll,同时执行实现了 IFoxInitialize 特性的函数 - // 注意这里的自动执行是在cad启动后,加载了dll之后执行,而不是运行命令后执行。 - - [IFoxInitialize] - public void InitOne() - { - // TODO 您想在加载dll之后自动执行的函数 - // 可以随便在哪里类里 可以多次实现 IFoxInitialize 特性 - } - -} - -// 其他的类中的函数: -// 实现自动接口之后,在任意一个函数上面使用此特性,减少每次改动 CmdINI 类 -public class AutoTest -{ - [IFoxInitialize] - public void Initialize() - { - // TODO 您想在加载dll之后自动执行的函数 - } - [IFoxInitialize] - public void InitTwo() - { - // TODO 您想在加载dll之后自动执行的函数 - // 可以随便在哪里类里 可以多次实现 IFoxInitialize 特性 - } - [IFoxInitialize(isInitialize: false)] // 特性的参数为false的时候就表示卸载时执行的函数 - public void Terminate() - { - // TODO 您想在关闭cad时自动执行的函数 - } -} -``` diff --git "a/docs/png/ifoxcad\347\224\250\346\210\267\344\272\244\346\265\201\347\276\244\347\276\244\344\272\214\347\273\264\347\240\201.png" "b/docs/png/ifoxcad\347\224\250\346\210\267\344\272\244\346\265\201\347\276\244\347\276\244\344\272\214\347\273\264\347\240\201.png" deleted file mode 100644 index a9d08c483b80f21d4b0ac6a0afe80f9b6b4233e6..0000000000000000000000000000000000000000 Binary files "a/docs/png/ifoxcad\347\224\250\346\210\267\344\272\244\346\265\201\347\276\244\347\276\244\344\272\214\347\273\264\347\240\201.png" and /dev/null differ diff --git a/docs/png/nuget.png b/docs/png/nuget.png deleted file mode 100644 index d0af980fedd9eca39d0e0bf787111685242994ac..0000000000000000000000000000000000000000 Binary files a/docs/png/nuget.png and /dev/null differ diff --git a/docs/png/nuget1.png b/docs/png/nuget1.png deleted file mode 100644 index 91983ffef3b246ea796296b14fe09963663de184..0000000000000000000000000000000000000000 Binary files a/docs/png/nuget1.png and /dev/null differ diff --git a/docs/png/standard.png b/docs/png/standard.png deleted file mode 100644 index dfc34fecb32120f54436115208a4abaea2dac516..0000000000000000000000000000000000000000 Binary files a/docs/png/standard.png and /dev/null differ diff --git "a/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" "b/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" index f96d39d487c1f6c2af8a2f3257fa3cc3bbfd619d..b282930055e78cca9a804f689b5f2ba0d4e80524 100644 --- "a/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" +++ "b/docs/\345\205\263\344\272\216IFoxCAD\347\232\204\346\236\266\346\236\204\350\257\264\346\230\216.md" @@ -71,42 +71,26 @@ IFoxCAD是基于NFOX类库的重制版,主要是提供一个最小化的内核 ## 一、组织结构图 - IFoxCAD - - - IFoxCAD.Basal - cad以外常用的类库 - - - LinqEx - linq扩展类 - - - LoopList - 环链表 - - - IFoxCAD.Cad - cad相关的类库 - - - Runtime - 包含系统级别的功能 - - - AcadVersion - cad版本号类 - - AssemInfo - 程序集信息 - - AutoRegAssem - 程序集加载类型 - - DBTrans - 事务处理类 - - Env - 系统管理类 - - SymbolTable - 符号表类 - - - ExtensionMethod - 扩展函数,以Ex结尾 - - - SymbolTableEx - 符号表扩展类 - - SymbolTableRecordEx - 符号表记录扩展类 - - EntityEx - 实体扩展类 - - 。。。。。。 - - - ResultData - - - 待补充。。。 - - - SelectionFilter - - - 待补充。。。 - - - IFoxCAD.WPF - wpf的mvvm模式相关的类库 - - ## 二、关于DBTrans类的说明 +``` + ├───CADShared -- 共享项目,所有的代码都在这里 + │ ├───Basal -- 一些基础类的函数 + │ │ ├───General + │ │ ├───Nullable + │ │ └───Win + │ ├───ExtensionMethod -- 扩展函数 + │ │ ├───Entity + │ │ ├───Geomerty + │ │ └───Jig + │ ├───Initialize -- 初始化 + │ ├───ResultData -- 扩展数据 + │ ├───Runtime -- 核心类 + │ └───SelectionFilter -- 选择集过滤器类 + ├───docs -- 架构及api定义说明文档 + ├───IFoxCAD.AutoCad -- AutoCAD的类库,内部除了globalusing外无其他代码 + └───Test -- 测试类 + ``` + +## 二、关于DBTrans类的说明 ### 2.1 为什么要构建DBTrans类? @@ -128,17 +112,18 @@ DBTrans的每个实例都具有这些属性,而这些属性就对应于cad的 属性: -- Top ---返回当前事务 +- Top ---返回当前DBTrans对象 - Database ---数据库 - Document ---文档 - Editor ---命令行 -- Trans ---事务管理器 +- Transaction ---事务 构造函数: -- DBTrans(Document doc = null, bool commit = true) +- DBTrans(Document? doc = null, bool commit = true, bool docLock = false) - DBTrans(Database database, bool commit = true) -- DBTrans(string fileName, bool commit = true) +- DBTrans(string fileName, bool commit = true, FileOpenMode fileOpenMode = FileOpenMode.OpenForReadAndWriteNoShare, + string? password = null, bool activeOpen = false) 符号表: @@ -152,10 +137,27 @@ DBTrans的每个实例都具有这些属性,而这些属性就对应于cad的 - ViewTable 视图表 - ViewportTable 视口表 +字典: + +- NamedObjectsDict 命名对象字典 +- GroupDict 组字典 +- MLeaderStyleDict 多重引线样式字典 +- MLStyleDict 多线样式字典 +- MaterialDict 材质字典 +- TableStyleDict 表格样式字典 +- VisualStyleDict 视觉样式字典 +- ColorDict 颜色字典 +- PlotSettingsDict 打印设置字典 +- PlotStyleNameDict 打印样式表名字典 +- LayoutDict 布局字典 +- DataLinkDict 数据链接字典 +- DetailViewStyleDict 详细视图样式字典 +- SectionViewStyleDict 剖面视图样式字典 + 方法: - GetObject ---根据对象id获取图元对象 -- 。。。 +- Task 前台后台任务分别处理 接口: diff --git "a/docs/\345\205\263\344\272\216\346\211\251\345\261\225\345\207\275\346\225\260\347\232\204\350\257\264\346\230\216.md" "b/docs/\345\205\263\344\272\216\346\211\251\345\261\225\345\207\275\346\225\260\347\232\204\350\257\264\346\230\216.md" deleted file mode 100644 index 41d9336e6e47afa45e72ad28de9cc455d510d320..0000000000000000000000000000000000000000 --- "a/docs/\345\205\263\344\272\216\346\211\251\345\261\225\345\207\275\346\225\260\347\232\204\350\257\264\346\230\216.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 关于扩展函数的说明 - -## 一、命名规则 - -扩展函数全部都放在 **ExtensionMethod** 文件夹里。 - -然后每个类别都需要分别建立一个以EX为结尾的文件。比如: - -DBObjectEx 实体对象扩展类 - -SymbolTableRecordEx 实体对象扩展类 - -EditorEx.cs 表示关于命令的扩展 - -![输入图片说明](https://images.gitee.com/uploads/images/2021/0701/225314_5b34dd8d_9063830.png "屏幕截图.png") diff --git a/README.md b/readme.md similarity index 96% rename from README.md rename to readme.md index f154371467399973e76bc2be57129c092d8cc8bd..1e9570c669295da03aa67b9dc0d74958db582b66 100644 --- a/README.md +++ b/readme.md @@ -12,7 +12,7 @@ 可以加群交流: -![IFoxCad用户交流群群二维码](./docs/png/ifoxcad用户交流群群二维码.png) +[点击链接加入群聊【IFoxCad交流群】](https://qm.qq.com/q/tJZELgdzHi) **QQ群为丐群,所以也可以加入qq频道交流:**