Author Topic: .NET SELECTION Routines  (Read 18341 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
.NET SELECTION Routines
« on: January 27, 2010, 03:32:31 AM »
LIBRARY THREAD for  AutoCAD SELECTIONS
 Members are encouraged to post any functions, methods, snips regarding
AutoCAD SELECTIONSS in .NET : C# ,  VB , F# , Python , etc

Feel free to include comments, descriptive notes, limitations,  and images to document your post.

Please post questions in a regular thread.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3590
  • (x-in)->[process]->(y-out) ... simples!
[Boo] Select all objects by type
« Reply #1 on: January 27, 2010, 02:31:09 PM »
just to get the ball rolling, here's an example of iterating over the modelspace block table record to retrieve all Solid3d and Line objects, change as per your required type.
I'll post an example using selection sets and filters as well shortly.

[added kwb] This is a Boo example
Boo is an object oriented statically typed programming language for the Common Language Infrastructure with a python inspired syntax.

Code: [Select]
public def SelectAll3dSolidsAndLines(prompt as string) as ObjectIdCollection:
db = HostApplicationServices.WorkingDatabase
ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
ids = ObjectIdCollection()
using tr = db.TransactionManager.StartTransaction():
//roll over the block table and get useable entity types:
bt = (tr.GetObject(db.BlockTableId, OpenMode.ForRead, false) as BlockTable)
if bt is null:
ed.WriteMessage('{0}Catastrophic error: Failed to open the BlockTable!', Environment.NewLine)
return

modelspace = (tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord)
if modelspace is null:
ed.WriteMessage('{0}Catastrophic error: Failed to open the modelspace btr!', Environment.NewLine)
return
for msid as ObjectId in modelspace:
l = (tr.GetObject(msid, OpenMode.ForRead) as Line)
if l is not null:
ids.Add(msid)

s = (tr.GetObject(msid, OpenMode.ForRead) as Solid3d)
if s is not null:
ids.Add(msid)
tr.Commit()
return ids
« Last Edit: January 27, 2010, 06:55:44 PM by Kerry Brown »
"Short cuts make long delays,' argued Pippin.
J.R.R. Tolkien

DaveWish

  • Guest
Re: .NET SELECTION Routines
« Reply #2 on: January 29, 2010, 12:49:24 PM »
That's beautiful code. Thanks

MickD

  • King Gator
  • Posts: 3590
  • (x-in)->[process]->(y-out) ... simples!
[Boo] Selection set with filter
« Reply #3 on: January 29, 2010, 07:57:59 PM »
I can't take all the credit, I pinched most of it from one of GlennR's posts  (thanks Glenn) and changed it to Boo ;)

Boo is a nice language, it's easy to read and use just like Python, probably even a little better in some respects.

Here's a selection set example as well although I was having some issues with Boo and enums. I have a work around though and have made a post at the Boo mailing lists to see what the problem is so hopefully it will be a short term fix. Basically I just use the actual enum assigned value for the comparison and this works fine.

Here'tis
Code: [Select]
// Autocad enums, we need to fudge these as Boo doesn't handle enums to well just yet :(
// these values are taken from the C++ ARX documentation on PromptStatus enums
// eNone 5000 No result
// eNormal 5100 Request succeeded
// eError -5001 Nonspecific error
// eCancel -5002 User canceled the request with a CTRL-C
// eRejected -5003 AutoCAD rejected the request as invalid
// eFailed -5004 Link failure, possibly with the LISP interpreter
// eKeyword -5005 Keyword returned from a "get" routine
// eDirect -5999 Passed to endGetPoint() if the getpoint was nested within
//                      another geometric value prompt (such as for angle), and the response
//                      entered was such a value rather than a point

public static def Select3dSolids(prompt as string) as (ObjectId):
ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
// set up some prompt options:
pso = PromptSelectionOptions()
pso.MessageForAdding = prompt
pso.AllowDuplicates = false
// create an sset filter to only grab 3d solids, an array of typed values
ssFilter = SelectionFilter((TypedValue(0, "3DSOLID"),)) // notice the ','!
// get the sset:
res as PromptSelectionResult = ed.GetSelection(pso, ssFilter)
if res.Status != 5100 or res.Status == -5002: // OK and Cancel enums.
return null
return res.Value.GetObjectIds()
"Short cuts make long delays,' argued Pippin.
J.R.R. Tolkien

fixo

  • Guest
Re: .NET SELECTION Routines
« Reply #4 on: August 27, 2010, 04:23:07 PM »
    ==  Continuous copy  ==

Code: [Select]
//inspired by Donnia Tabor-Hanson's (CadMama) continuous copy lisp 'cc.lsp'
[CommandMethod("CC")]
        public static void ContinuousCopy()

        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;

            Database db = HostApplicationServices.WorkingDatabase;

            Editor ed = doc.Editor;

            Transaction tr = db.TransactionManager.StartTransaction();

            BlockTableRecord btr =

                   (BlockTableRecord)tr.GetObject(

                   db.CurrentSpaceId,

                   OpenMode.ForWrite,

                   false);

            using (tr)
            {
                PromptEntityOptions peo = new PromptEntityOptions("\nSelect Object >>");

                peo.SetRejectMessage("\nNothing selected >>");

                PromptEntityResult res;

                res = ed.GetEntity(peo);

                if (res.Status != PromptStatus.OK)

                    return;

                Entity ent = (Entity)tr.GetObject(res.ObjectId, OpenMode.ForRead);

                if (ent == null)

                    return;

                Point3d pt = res.PickedPoint;

                PromptAngleOptions pao =

                            new PromptAngleOptions("\nSelect angle: ");

                PromptDoubleResult ares;

                ares = ed.GetAngle(pao);

                if (ares.Status != PromptStatus.OK)

                    return;

                double ang = ares.Value;

                PromptDistanceOptions pdo =

    new PromptDistanceOptions("\nEnter a distance >>");

                pdo.AllowNone = true;

                pdo.UseDefaultValue = true;

                pdo.DefaultValue = 12.0;

                pdo.Only2d = true;

                PromptDoubleResult dres;

                dres = ed.GetDistance(pdo);

                if (dres.Status != PromptStatus.OK)

                    return;

                double dist = dres.Value;

                double step = dist;

                PromptKeywordOptions pko = new PromptKeywordOptions("\nCopy or Break out? [Copy/Break]:", "Copy Break");

                pko.AllowNone = true;

                pko.Keywords.Default = "Copy";

                PromptResult kres = ed.GetKeywords(pko);

                ed.WriteMessage("\n" + kres.StringResult);

                while (kres.StringResult == "Copy")
                {
                    Entity cent =(Entity) ent.Clone() as Entity;

                    Point3d topt = PolarPoint(pt, ang, dist);

                    Matrix3d mtx = Matrix3d.Displacement(pt.GetVectorTo(topt));

                    cent.TransformBy(mtx);

                    btr.AppendEntity(cent);

                    tr.AddNewlyCreatedDBObject(cent, true);

                    db.TransactionManager.QueueForGraphicsFlush();

                    dist = dist+step;

                    kres = ed.GetKeywords(pko);

                    if (kres.StringResult != "Copy") break;
                }

                tr.Commit();
            }
        }

        // by Tony Tanzillo
        public static Point3d PolarPoint(Point3d basepoint, double angle, double distance)
        {
            return new Point3d(

            basepoint.X + (distance * Math.Cos(angle)),

            basepoint.Y + (distance * Math.Sin(angle)),

            basepoint.Z);
        }

gile

  • Water Moccasin
  • Posts: 2492
  • Marseille, France
Re: .NET SELECTION Routines
« Reply #5 on: November 20, 2011, 05:16:46 AM »
Hi,

Here's a little example of using the Editor.SelectionAdded event to filter a selection.

This example defines an Editor extension method to select only Curve entities, an additional selection filter can be used.

Code: [Select]
        public static PromptSelectionResult GetCurveSelection(this Editor ed, params TypedValue[] filter)
        {
            ed.SelectionAdded += new SelectionAddedEventHandler(OnCurveSelectionAdded);
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            ed.SelectionAdded -= new SelectionAddedEventHandler(OnCurveSelectionAdded);
            return psr;
        }

        static void OnCurveSelectionAdded(object sender, SelectionAddedEventArgs e)
        {
            ObjectId[] ids = e.AddedObjects.GetObjectIds();
            for (int i = 0; i < ids.Length; i++)
            {
                if (!ids[i].ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Curve))))
                    e.Remove(i);
            }
        }
Speaking English as a French Frog

gile

  • Water Moccasin
  • Posts: 2492
  • Marseille, France
Re: .NET SELECTION Routines
« Reply #6 on: June 30, 2013, 05:09:07 AM »
Hi,

This is just a example (related to this thread)  to show how it is possible to change the filtering criteria during the selection using Editor.SelectionAdded event.

In this example, the selection starts filtering lines and allows the user to change the filtered entities to circles or polylines by specifying keywords.

C#
Code - C#: [Select]
  1. using System.Collections.Generic;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Runtime;
  6.  
  7. namespace SelectionSample
  8. {
  9.     public class CommandMethods
  10.     {
  11.         private string keyWord;
  12.  
  13.         [CommandMethod("Test")]
  14.         public void Test()
  15.         {
  16.             Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  17.  
  18.             this.keyWord = "LIne";
  19.  
  20.             PromptSelectionOptions opt = new PromptSelectionOptions();
  21.             opt.SetKeywords("[CIrcle/LIne/POlyline]", "CIrcle LIne POlyline");
  22.             opt.MessageForAdding = "\nSelect objects or " + opt.Keywords.GetDisplayString(true);
  23.             opt.KeywordInput += onKeywordInput;
  24.  
  25.             ed.SelectionAdded += onSelectionAdded;
  26.             PromptSelectionResult psr = ed.GetSelection(opt);
  27.             ed.SelectionAdded -= onSelectionAdded;
  28.             if (psr.Status == PromptStatus.OK)
  29.                 ed.SetImpliedSelection(psr.Value);
  30.         }
  31.  
  32.         private void onKeywordInput(object sender, SelectionTextInputEventArgs e)
  33.         {
  34.             this.keyWord = e.Input;
  35.         }
  36.  
  37.         private void onSelectionAdded(object sender, SelectionAddedEventArgs e)
  38.         {
  39.             RXClass rxc;
  40.             switch (this.keyWord)
  41.             {
  42.                 case "POlyline": rxc = RXClass.GetClass(typeof(Polyline)); break;
  43.                 case "CIrcle": rxc = RXClass.GetClass(typeof(Circle)); break;
  44.                 default: rxc = RXClass.GetClass(typeof(Line)); break;
  45.             }
  46.             ObjectId[] ids = e.AddedObjects.GetObjectIds();
  47.             for (int i = 0; i < ids.Length; i++)
  48.             {
  49.                 if (ids[i].ObjectClass != rxc)
  50.                     e.Remove(i);
  51.             }
  52.         }
  53.     }
  54. }

VB
Code - vb.net: [Select]
  1. Imports System.Collections.Generic
  2. Imports Autodesk.AutoCAD.ApplicationServices
  3. Imports Autodesk.AutoCAD.DatabaseServices
  4. Imports Autodesk.AutoCAD.EditorInput
  5. Imports Autodesk.AutoCAD.Runtime
  6.  
  7. Namespace SelectionSample
  8.  
  9.     Public Class CommandMethods
  10.  
  11.         Private keyWord As String
  12.  
  13.         <CommandMethod("Test")> _
  14.         Public Sub Test()
  15.             Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
  16.  
  17.             Me.keyWord = "LIne"
  18.  
  19.             Dim opt As New PromptSelectionOptions()
  20.             opt.SetKeywords("[CIrcle/LIne/POlyline]", "CIrcle LIne POlyline")
  21.             opt.MessageForAdding = vbLf & "Select objects or " & opt.Keywords.GetDisplayString(True)
  22.             AddHandler opt.KeywordInput, AddressOf onKeywordInput
  23.  
  24.             AddHandler ed.SelectionAdded, AddressOf onSelectionAdded
  25.             Dim psr As PromptSelectionResult = ed.GetSelection(opt)
  26.             RemoveHandler ed.SelectionAdded, AddressOf onSelectionAdded
  27.             If psr.Status = PromptStatus.OK Then
  28.                 ed.SetImpliedSelection(psr.Value)
  29.             End If
  30.         End Sub
  31.  
  32.         Private Sub onKeywordInput(sender As Object, e As SelectionTextInputEventArgs)
  33.             Me.keyWord = e.Input
  34.         End Sub
  35.  
  36.         Private Sub onSelectionAdded(sender As Object, e As SelectionAddedEventArgs)
  37.             Dim rxc As RXClass
  38.             Select Case Me.keyWord
  39.                 Case "POlyline"
  40.                     rxc = RXClass.GetClass(GetType(Polyline))
  41.                     Exit Select
  42.                 Case "CIrcle"
  43.                     rxc = RXClass.GetClass(GetType(Circle))
  44.                     Exit Select
  45.                 Case Else
  46.                     rxc = RXClass.GetClass(GetType(Line))
  47.                     Exit Select
  48.             End Select
  49.             Dim ids As ObjectId() = e.AddedObjects.GetObjectIds()
  50.             For i As Integer = 0 To ids.Length - 1
  51.                 If ids(i).ObjectClass <> rxc Then
  52.                     e.Remove(i)
  53.                 End If
  54.             Next
  55.         End Sub
  56.  
  57.     End Class
  58.  
  59. End Namespace

F#
Code - F#: [Select]
  1. module SelectionSample
  2.  
  3. open System.Collections.Generic
  4. open Autodesk.AutoCAD.ApplicationServices
  5. open Autodesk.AutoCAD.DatabaseServices
  6. open Autodesk.AutoCAD.EditorInput
  7. open Autodesk.AutoCAD.Runtime
  8.  
  9. [<CommandMethod("Test")>]
  10. let test () =
  11.     let ed = Application.DocumentManager.MdiActiveDocument.Editor
  12.  
  13.     let keyWord = ref "LIne"
  14.  
  15.     let opt = new PromptSelectionOptions()
  16.     opt.SetKeywords("[CIrcle/LIne/POlyline]", "CIrcle LIne POlyline")
  17.     opt.MessageForAdding <- "\nSelect objects or " + opt.Keywords.GetDisplayString(true)
  18.     opt.KeywordInput.Add(fun (e: SelectionTextInputEventArgs) -> keyWord := e.Input)
  19.  
  20.     let onSelectionAdded =
  21.         new SelectionAddedEventHandler(fun _ e ->
  22.             let rxc =
  23.                 RXClass.GetClass(
  24.                     match !keyWord with
  25.                     | "CIrcle"   -> typeof<Circle>
  26.                     | "POlyline" -> typeof<Polyline>
  27.                     | _          -> typeof<Line>)
  28.             e.AddedObjects.GetObjectIds()
  29.             |> Array.iteri(fun i id -> if id.ObjectClass <> rxc then e.Remove(i)))
  30.  
  31.     ed.SelectionAdded.AddHandler(onSelectionAdded)
  32.     let psr = ed.GetSelection(opt)
  33.     ed.SelectionAdded.RemoveHandler(onSelectionAdded)
  34.     if psr.Status = PromptStatus.OK then
  35.         ed.SetImpliedSelection(psr.Value)
Speaking English as a French Frog

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: .NET SELECTION Routines
« Reply #7 on: June 30, 2013, 07:46:17 PM »
Very nice gile! I had desired this behavior but thought along the lines of Mr. Webb...
Do you think it would be worth adding another collection to track all raw selection so that when filter parameters are changed the user doesn't have to reselect objects which were excluded by previous filter parameters?

gile

  • Water Moccasin
  • Posts: 2492
  • Marseille, France
Re: .NET SELECTION Routines
« Reply #8 on: May 06, 2023, 11:56:12 AM »
Hi,

On a French forum, someone asked how to make a modeless dialog to display the total length of the selected entities as well as the distribution by entity type.
I thought it was a good example to show an example of binding an ObsevableCollection from the AutoCAD.UIBindings API with a WPF GUI using the MVVM design pattern.

Model
Here the Model is limited to the observable collection returned by UIBindings.Collections.Selection.

View
The GUI displays the total length of all selected objects in a TextBlock and the lengths by type in the rows of a ListView with three columns one for the type of entity, one for the quantity and one for the length.
Code - XML: [Select]
  1. <UserControl x:Class="ObservableSelectionSample.SelectionView"
  2.             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  5.             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6.             xmlns:local="clr-namespace:ObservableSelectionSample"
  7.             mc:Ignorable="d"
  8.             d:DesignHeight="150" d:DesignWidth="220">
  9.     <Grid Background="WhiteSmoke">
  10.         <Grid.RowDefinitions>
  11.             <RowDefinition Height="Auto" />
  12.             <RowDefinition />
  13.         </Grid.RowDefinitions>
  14.         <StackPanel Grid.Row="0" Margin="5"  Orientation="Horizontal">
  15.             <TextBlock Margin="15,0,5,0">Total =</TextBlock>
  16.             <TextBlock Text="{Binding Total, StringFormat={}{0:0.00}}" />
  17.         </StackPanel>
  18.         <ListView Grid.Row="1" Margin="5" ItemsSource="{Binding Selection}">
  19.             <ListView.ItemContainerStyle>
  20.                 <Style TargetType="ListViewItem">
  21.                     <Setter Property="HorizontalContentAlignment" Value="Stretch" />
  22.                 </Style>
  23.             </ListView.ItemContainerStyle>
  24.             <ListView.View>
  25.                 <GridView>
  26.                     <GridViewColumn Header="Type" Width="80" DisplayMemberBinding="{Binding Name}" />
  27.                     <GridViewColumn Header="Qty" Width="40">
  28.                         <GridViewColumn.CellTemplate>
  29.                             <DataTemplate>
  30.                                 <TextBlock HorizontalAlignment="Right" Text="{Binding Count}" />
  31.                             </DataTemplate>
  32.                         </GridViewColumn.CellTemplate>
  33.                     </GridViewColumn>
  34.                     <GridViewColumn Header="Length" Width="80">
  35.                         <GridViewColumn.CellTemplate>
  36.                             <DataTemplate>
  37.                                 <TextBlock HorizontalAlignment="Right" Text="{Binding Length, StringFormat={}{0:0.00}}" />
  38.                             </DataTemplate>
  39.                         </GridViewColumn.CellTemplate>
  40.                     </GridViewColumn>
  41.                 </GridView>
  42.             </ListView.View>
  43.         </ListView>
  44.     </Grid>
  45. </UserControl>
  46.  

As usual with the MVVM design pattern, the code behind contains only the definition of the DataContext.
Code - C#: [Select]
  1. using System.Windows.Controls;
  2.  
  3. namespace ObservableSelectionSample
  4. {
  5.     public partial class SelectionView : UserControl
  6.     {
  7.         public SelectionView()
  8.         {
  9.             InitializeComponent();
  10.             DataContext = new SelectionViewModel();
  11.         }
  12.     }
  13. }

The UserControl is added to a palette (PaletteSet).
Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.Windows;
  3.  
  4. using System;
  5.  
  6. namespace ObservableSelectionSample
  7. {
  8.     internal class SelectionPalette : PaletteSet
  9.     {
  10.         static bool wasVisible;
  11.  
  12.         public SelectionPalette()
  13.             : base("Selection", "SELPAL", new Guid("{CD633456-90D4-473A-9F73-DA881A7BA546}"))
  14.         {
  15.             Style =
  16.                 PaletteSetStyles.ShowAutoHideButton |
  17.                 PaletteSetStyles.ShowCloseButton |
  18.                 PaletteSetStyles.ShowPropertiesMenu;
  19.             MinimumSize = new System.Drawing.Size(230, 150);
  20.  
  21.             AddVisual("", new SelectionView());
  22.  
  23.             // Auto hiding of the palette when none document is active (no document state)
  24.             var docs = Application.DocumentManager;
  25.             docs.DocumentBecameCurrent += (s, e) =>
  26.                 Visible = e.Document == null ? false : wasVisible;
  27.             docs.DocumentCreated += (s, e) =>
  28.                 Visible = wasVisible;
  29.             docs.DocumentToBeDeactivated += (s, e) =>
  30.                 wasVisible = Visible;
  31.             docs.DocumentToBeDestroyed += (s, e) =>
  32.             {
  33.                 wasVisible = Visible;
  34.                 if (docs.Count == 1)
  35.                     Visible = false;
  36.             };
  37.         }
  38.     }
  39. }
  40.  

ViewModel
The goal is to adapt the Model data into types exploitable by the View via DataBinding. In this case we need a property of type ObservableCollection whose elements group the selected measurable curves by type and expose properties for the entity type, the cumulative length and the quantity of entities.
Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.AutoCAD.Windows.Data;
  5.  
  6. using System.Collections.ObjectModel;
  7. using System.ComponentModel;
  8. using System.Linq;
  9.  
  10. namespace ObservableSelectionSample
  11. {
  12.     public class SelectionViewModel : INotifyPropertyChanged
  13.     {
  14.         #region INotifyPropertyChanged implementation
  15.         public event PropertyChangedEventHandler PropertyChanged;
  16.  
  17.         protected void NotifyPropertyChanged(string propertyName) =>
  18.             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  19.         #endregion
  20.  
  21.         // Type of item of the ObsevableCollection.
  22.         public struct CurveGroup
  23.         {
  24.             // Properties bound to the ListView columns
  25.             public int Count { get; set; }
  26.             public double Length { get; set; }
  27.             public string Name { get; set; }
  28.         }
  29.  
  30.         DataItemCollection itemCollection;
  31.         double total;
  32.  
  33.         // Property bound to the ListView
  34.         public ObservableCollection<CurveGroup> Selection { get; }
  35.  
  36.         // Property bound to the TextBlock
  37.         public double Total
  38.         {
  39.             get { return total; }
  40.             set { total = value; NotifyPropertyChanged(nameof(Total)); }
  41.         }
  42.  
  43.         // Initialization and subscription to CollectionChanged and ItemsChanged events of the itemCollection
  44.         public SelectionViewModel()
  45.         {
  46.             Selection = new ObservableCollection<CurveGroup>();
  47.             itemCollection = Application.UIBindings.Collections.Selection;
  48.             itemCollection.CollectionChanged += (s, e) => Update();
  49.             itemCollection.ItemsChanged += (s, e) => Update();
  50.         }
  51.  
  52.         // Updating Selection and Total properties.
  53.         private void Update()
  54.         {
  55.             bool IsValidCurve(RXClass rXClass) =>
  56.                 rXClass.IsDerivedFrom(RXObject.GetClass(typeof(Curve))) &&
  57.                 rXClass.DxfName != "RAY" && rXClass.DxfName != "XLINE";
  58.             Selection.Clear();
  59.             using (var tr = new OpenCloseTransaction())
  60.             {
  61.                 var groups = itemCollection
  62.                     .Cast<IDataItem>()
  63.                     .Where(item => IsValidCurve(item.ObjectId.ObjectClass))
  64.                     .Select(item => (Curve)tr.GetObject(item.ObjectId, OpenMode.ForRead))
  65.                     .GroupBy(curve => curve.GetType().Name)
  66.                     .Select(group => new CurveGroup
  67.                     {
  68.                         Count = group.Count(),
  69.                         Length = group.Sum(c => c.GetDistanceAtParameter(c.EndParam)),
  70.                         Name = group.Key
  71.                     });
  72.                 foreach (var group in groups)
  73.                     Selection.Add(group);
  74.                 Total = Selection.Sum(x => x.Length);
  75.             }
  76.         }
  77.     }
  78. }
  79.  

And finally a command to display the palette.
Code - C#: [Select]
  1. using Autodesk.AutoCAD.Runtime;
  2.  
  3. namespace ObservableSelectionSample
  4. {
  5.     public class Commands
  6.     {
  7.         static SelectionPalette palette;
  8.  
  9.         [CommandMethod("SELPAL")]
  10.         public void ShowSelectionPalette()
  11.         {
  12.             if (palette == null)
  13.                 palette = new SelectionPalette();
  14.             palette.Visible = true;
  15.         }
  16.     }
  17. }

« Last Edit: May 06, 2023, 02:49:00 PM by gile »
Speaking English as a French Frog

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2067
  • class keyThumper<T>:ILazy<T>
Re: .NET SELECTION Routines
« Reply #9 on: May 06, 2023, 05:09:53 PM »
Very nice Gilles.
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00


some people complain about loading the dishwasher

Sometimes the question is more important than the answer.

HOSNEYALAA

  • Newt
  • Posts: 103
Re: .NET SELECTION Routines
« Reply #10 on: May 09, 2023, 03:53:30 AM »
HI
Very nice code
@gile and @kdub_nz

My English is not good

Maybe can you attached project for this code
I have no idea how that is possible , compile it into a project

Thanks in advance

gile

  • Water Moccasin
  • Posts: 2492
  • Marseille, France
Re: .NET SELECTION Routines
« Reply #11 on: May 10, 2023, 02:27:15 AM »
@HOSNEYALAA
I posted this code mainly to show how usefull (and powerfull) could be the UIBindings API and how it's easy to use with WPF Bindings.
Anyway, if you're interested by using the plug-in as is, you can download the attached .zip file, unblock it, extract and run the SelectionPaletteSetup.exe installer.
« Last Edit: May 10, 2023, 09:53:37 AM by gile »
Speaking English as a French Frog

HOSNEYALAA

  • Newt
  • Posts: 103
Re: .NET SELECTION Routines
« Reply #12 on: May 10, 2023, 08:19:29 AM »

Thank you very much
appeared problem



gile

  • Water Moccasin
  • Posts: 2492
  • Marseille, France
Re: .NET SELECTION Routines
« Reply #13 on: May 10, 2023, 09:54:43 AM »
OOps... Updated the attachment.
Speaking English as a French Frog

HOSNEYALAA

  • Newt
  • Posts: 103
Re: .NET SELECTION Routines
« Reply #14 on: May 11, 2023, 01:08:06 AM »

THANK YOU