Retrieve and edit Xdata

Retrieve and edit Xdata

Anonymous
Not applicable
2,153 Views
4 Replies
Message 1 of 5

Retrieve and edit Xdata

Anonymous
Not applicable

I have written two functions that are working properly when executed from the command line. the the first function  allows selection of an object and populates the text boxes by reading the xdata.  The second function writes the xdata to the object from values in the textboxes. I would like to select an object populate the form textboxes from xdata then change the xdata on the form, and then write the xdata out.  I think the first function should fire on the form load and the second should fire on the button click. How do i keep the object selected throughout the prosess?

 

MIke 

0 Likes
2,154 Views
4 Replies
Replies (4)
Message 2 of 5

FRFR1426
Collaborator
Collaborator
Show us the code, because I don't understand what you mean by "selected".
Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr
0 Likes
Message 3 of 5

Anonymous
Not applicable

I think you should add a handler on the imliedselection changes...

 

Something like this:

Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices

Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime

<Assembly: ExtensionApplication(GetType(TestXdata.XdataCommands))> 
Namespace TestXdata
    Public Class XdataCommands
        Implements IExtensionApplication

        Public Sub Initialize() Implements IExtensionApplication.Initialize
            Dim dm As Autodesk.AutoCAD.ApplicationServices.DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
            Dim doc As Autodesk.AutoCAD.ApplicationServices.Document = dm.MdiActiveDocument
            AddHandler dm.DocumentCreated, New DocumentCollectionEventHandler(AddressOf InjectToNewDoc)
            AddHandler doc.ImpliedSelectionChanged, New System.EventHandler(AddressOf MyCustomSelection)
        End Sub

        Public Sub InjectToNewDoc()
            Dim dm As Autodesk.AutoCAD.ApplicationServices.DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
            Dim doc As Autodesk.AutoCAD.ApplicationServices.Document = dm.MdiActiveDocument
            AddHandler doc.ImpliedSelectionChanged, New System.EventHandler(AddressOf MyCustomSelection)
        End Sub

        Public Sub Terminate() Implements IExtensionApplication.Terminate

        End Sub

        Public Sub MyCustomSelection(sender As Object, e As System.EventArgs)
            Dim dm As Autodesk.AutoCAD.ApplicationServices.DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
            Dim doc As Autodesk.AutoCAD.ApplicationServices.Document = dm.MdiActiveDocument

            Dim psr As PromptSelectionResult = doc.Editor.SelectImplied
            If psr.Status = PromptStatus.OK Then
                If psr.Value.Count >= 1 Then
                    Using dl As DocumentLock = doc.LockDocument
                        Using tr As Transaction = doc.Database.TransactionManager.StartTransaction
                            For Each so As SelectedObject In psr.Value
                                'Get your Xdata...
                                'add data to your form...
                            Next
                        End Using
                    End Using
                End If
            End If
        End Sub
    End Class

End Namespace
0 Likes
Message 4 of 5

_gile
Consultant
Consultant

Hi,

 

It's quite difficult to reply without knowing what kind of dialog you're using (modal or modeless/palette).

 

Anyway, here's a minimalist sample using a simple modal dialog.

 

dialog.png

 

 

using System.Windows.Forms;

namespace XdataDialogSample
{
    public partial class XDataDialog : Form
    {
        public XDataDialog()
        {
            InitializeComponent();

            // this can also be done through Visual Studio properties window
            this.btnOK.DialogResult = DialogResult.OK;
            this.btnCancel.DialogResult = DialogResult.Cancel;
            this.AcceptButton = this.btnOK;
            this.CancelButton = this.btnCancel;
        }

        // expose the textbox content outside the XDataDialog class
        public string DataValue
        {
            get { return this.txtData.Text; }
            set { this.txtData.Text = value; }
        }
    }
}
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;

[assembly: CommandClass(typeof(XdataDialogSample.Commands))]

namespace XdataDialogSample
{
    public class Commands
    {
        [CommandMethod("Cmd1")]
        public void Cmd1()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            // select an entity
            var getEntityResult = ed.GetEntity("\nSelect object: ");
            if (getEntityResult.Status != PromptStatus.OK)
                return;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                // open the entity and look for xdata
                var entity = (Entity)tr.GetObject(getEntityResult.ObjectId, OpenMode.ForRead);
                var resbuf = entity.GetXDataForApplication("SomeApp");
                // if not found
                if (resbuf == null)
                {
                    Application.ShowAlertDialog("None xdata");
                    return;
                }
                // get the data value
                var data = resbuf.AsArray();
                var value = data[1].Value.ToString();
                // create an instance of XDataDialog
                var dialog = new XDataDialog();
                // populate the xdata value in the dialog textbox
                dialog.DataValue = value;
                // show the dialog
                var dialogResult = Application.ShowModalDialog(dialog);
                // if the user clicked OK, update the xdata
                if (dialogResult == System.Windows.Forms.DialogResult.OK)
                {
                    data[1] = new TypedValue(1000, dialog.DataValue);
                    entity.UpgradeOpen();
                    entity.XData = new ResultBuffer(data);
                }
                tr.Commit();
            }
        }
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 5

_gile
Consultant
Consultant

Hi,

 

Another minimalist sample using a Palette (modeless) with a Wpf control and MVVM design pattern.

 

 palette.png

 

Model part (AutoCAD related stuf)

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Internal;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace XDataPaletteSample.Model
{
    class AcadWorker
    {
        private static ObjectId _id;
        private const string _appName = "SomeApp";

        public static string GetXData()
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            Utils.SetFocusToDwgView();
            var result = ed.GetEntity("\nSelect Object: ");
            if (result.Status != PromptStatus.OK)
                return null;
            _id = result.ObjectId;
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var ent = (Entity)tr.GetObject(_id, OpenMode.ForRead);
                var resbuf = ent.GetXDataForApplication(_appName);
                if (resbuf == null)
                    return "";
                return resbuf.AsArray()[1].Value.ToString();
            }
        }

        public static void SetXData(string data)
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            using (doc.LockDocument())
            using (var tr = db.TransactionManager.StartTransaction())
            {
                var regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
                if (!regAppTable.Has(_appName))
                {
                    regAppTable.UpgradeOpen();
                    var regApp = new RegAppTableRecord();
                    regApp.Name = _appName;
                    regAppTable.Add(regApp);
                    tr.AddNewlyCreatedDBObject(regApp, true);
                }
                var resbuf = string.IsNullOrEmpty(data) ?
                    new ResultBuffer(new TypedValue(1001, _appName)) :
                    new ResultBuffer(new TypedValue(1001, _appName), new TypedValue(1000, data));
                var ent = tr.GetObject(_id, OpenMode.ForWrite);
                ent.XData = resbuf;
                tr.Commit();
            }
        }
    }
}

 

View part

The xaml file:

<UserControl x:Class="XDataPaletteSample.View.XDataControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:ViewModel="clr-namespace:XDataPaletteSample.ViewModel"
             mc:Ignorable="d" 
             d:DesignHeight="135" d:DesignWidth="300">
    <UserControl.DataContext>
        <ViewModel:MainViewModel/>
    </UserControl.DataContext>
    <Grid Background="WhiteSmoke">
        <StackPanel>
            <Button Width="100" Content="Select Object" Margin="10" Command="{Binding SelectCommand}"/>
            <StackPanel Orientation="Horizontal" Margin="10">
                <Label Content="Value: " Margin="0,0,5,0"/>
                <TextBox Height="20" Width="225" Text="{Binding DataValue}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="10" HorizontalAlignment="Center">
                <Button Width="75" Margin="0,0,10,0" Content="Write data" IsEnabled="{Binding Enabled}" Command="{Binding WriteDataCommand}"/>
                <Button Width="75" Margin="10,0,0,0" Content="Cancel" IsEnabled="{Binding Enabled}" Command="{Binding CancelCommand}"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>

the code behind:

using System.Windows.Controls;

namespace XDataPaletteSample.View
{
    public partial class XDataControl : UserControl
    {
        public XDataControl()
        {
            InitializeComponent();
        }
    }
}

 

 

ViewModel part (including the classical ObservableObject and RelayCommand helpers)

using System.ComponentModel;

namespace XDataPaletteSample.ViewModel
{
    class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
using System;
using System.Windows.Input;

namespace XDataPaletteSample.ViewModel
{
    class RelayCommand : ICommand
    {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;

        public RelayCommand(Action execute)
            : this((_) => execute()) { }

        public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");
            _execute = execute;
            _canExecute = canExecute ?? ((_) => true);
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    }
}
using System;
using System.Windows.Input;
using XDataPaletteSample.Model;

namespace XDataPaletteSample.ViewModel
{
    class MainViewModel : ObservableObject
    {
        private string _dataValue;

        public string DataValue
        {
            get { return _dataValue; }
            set
            {
                _dataValue = value;
                this.Enabled = _dataValue != null;
                RaisePropertyChanged("DataValue");
                RaisePropertyChanged("Enabled");
            }
        }

        public bool Enabled { get; set; }

        public ICommand SelectCommand
        {
            get { return new RelayCommand(() => this.DataValue = AcadWorker.GetXData()); }
        }

        public ICommand WriteDataCommand
        {
            get
            {
                return new RelayCommand(
                    () => { AcadWorker.SetXData(this.DataValue); this.DataValue = null; });
            }
        }

        public ICommand CancelCommand
        {
            get { return new RelayCommand(() => this.DataValue = null); }
        }
    }
}

 

And the command to display the palette

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;

[assembly: CommandClass(typeof(XDataPaletteSample.CommandMethods))]

namespace XDataPaletteSample
{
    public class CommandMethods
    {
        private static PaletteSet _palette;

        [CommandMethod("XDATAPALETTE")]
        public static void XDataPaletteCommand()
        {
            if (_palette == null)
            {
                _palette = new PaletteSet("XDataPalette", new Guid("{2E9CEAF7-5CFB-4B5D-A2B9-B8BB215DB604}"));
                _palette.Style =
                    PaletteSetStyles.ShowAutoHideButton |
                    PaletteSetStyles.ShowCloseButton |
                    PaletteSetStyles.ShowPropertiesMenu;
                _palette.MinimumSize = new System.Drawing.Size(330, 150);
                _palette.Name = "XData Palette";
                _palette.AddVisual("XDataControl", new View.XDataControl());
            }
            _palette.Visible = true;
        }
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub