I received this request from Mateusz Andrzejczak, over the weekend:
I have problem with LineTypeDialog. Your part of the code is working perfectly, but i have problem with modifying the values. I have a SelectionSet that holds all object that are selected with using a filter. I want to use LineTypeDialog to select linetype and then accept so all the object in selection set will change to selected linetype. I'm working with this for a few hours and it's not working. Any tip for me?
The question related to this old post. I started by sending Mateusz a link to this follow-up post, which shows how to display various AutoCAD dialogs and then apply the chosen properties to a selected entity.
But then I thought about it, and decided to go ahead and implement Mateusz’s request, showing a couple of additional “nice-to-have” features beyond just dealing with a selection set:
- Make sure the command works with the pickfirst selection set (so it can be called using the noun-verb interaction paradigm)
- Check the selection set to see whether the selected entities have the same linetype ID: if so, select that as the default in the dialog
Nothing really earth-shattering, but it does show the use of the linetype dialog in a somewhat more realistic scenario.
Here’s the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
namespace EntityProperties
{
public class Commands
{
[CommandMethod("SLT", CommandFlags.UsePickSet)]
public void SetLineType()
{
var doc = Application.DocumentManager.MdiActiveDocument;
if (doc == null)
return;
var ed = doc.Editor;
// Get the pickfirst selection set or ask the user to
// select some entities
var psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK || psr.Value.Count == 0)
return;
using (var tr = doc.TransactionManager.StartTransaction())
{
// Get the IDs of the selected objects
var ids = psr.Value.GetObjectIds();
// Loop through in read-only mode, checking whether the
// selected entities have the same linetype
// (if so, it'll be set in ltId, otherwise different will
// be true)
var ltId = ObjectId.Null;
bool different = false;
foreach (ObjectId id in ids)
{
// Get the entity for read
var ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
// On the first iteration we store the linetype Id
if (ltId == ObjectId.Null)
ltId = ent.LinetypeId;
else
{
// On subsequent iterations we check against the
// first one and set different to be true if they're
// not the same
if (ltId != ent.LinetypeId)
{
different = true;
break;
}
}
}
// Now we can display our linetype dialog with the common
// linetype selected (if they have the same one)
var ltd = new LinetypeDialog();
if (!different)
ltd.Linetype = ltId;
var dr = ltd.ShowDialog();
if (dr != System.Windows.Forms.DialogResult.OK)
return; // We might also commit before returning
// Assuming we have a different linetype selected
// (or the entities in the selected have different
// linetypes to start with) then we'll loop through
// to set the new linetype
if (different || ltId != ltd.Linetype)
{
foreach (ObjectId id in ids)
{
// This time we need write access
var ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
// Set the linetype if it's not the same
if (ent.LinetypeId != ltd.Linetype)
ent.LinetypeId = ltd.Linetype;
}
}
// Finally we commit the transaction
tr.Commit();
}
}
}
}
When you run the SLT command, you’ll see the linetype dialog has a default entry highlighted in the case where all the selected entities have the same linetype: