Author Topic: Import text style, dim style, leader style drop down list from Autocad  (Read 5900 times)

0 Members and 1 Guest are viewing this topic.

latour_g

  • Newt
  • Posts: 184
Hi,

I would like to know if there is a way to import the drop down list from the style toolbar in my tool palette ? I would like to incorporate them in my tool palette without doing it from scratch.
Is it doable ? I try to google that but I can't find my answer.

Thank you
« Last Edit: April 27, 2016, 03:06:18 PM by latour_g »

lamarn

  • Swamp Rat
  • Posts: 636
Maybe You should take a look at Lee Mac Steal from drawing/ template command..
Design is something you should do with both hands. My 2d hand , my 3d hand ..

latour_g

  • Newt
  • Posts: 184
I looked at it but it's not what I'm looking for.  Here is another pic, I want to put Autocad list in my tool palette.

ChrisCarlson

  • Guest
Do you just want to list the available (within the current dwg) or something else?

Code - C#: [Select]
  1. textStyleTable = (TextStyleTable)tr.GetObject(db.TextStyleTableId, OpenMode.ForRead);

latour_g

  • Newt
  • Posts: 184
Yes but I don't want to validate the list when the user change drawing or add/remove style.   So I thought if I took the list from Autocad it would always be up to date.
But maybe it's not doable !

MexicanCustard

  • Swamp Rat
  • Posts: 705
Look at Application.UIBindings.Collections.  You didn't mention the architecture you're using to create the palette.  If you're using WPF you can bind directly to the collections.
Revit 2019, AMEP 2019 64bit Win 10

ChrisCarlson

  • Guest
Potentially?

Code - C#: [Select]
  1. TextStyles = Application.UIBindings.Collections.TextStyles;

Code - Text: [Select]
  1. <ComboBox ItemsSource="{Binding TextStyles}">

MSTG007

  • Gator
  • Posts: 2603
  • I can't remeber what I already asked! I need help!
How did you get your tool palette to look like that? That's cool. Mine are just basic icon with text next to them.
Civil3D 2020

ChrisCarlson

  • Guest
How did you get your tool palette to look like that? That's cool. Mine are just basic icon with text next to them.

Custom .NET palette.

latour_g

  • Newt
  • Posts: 184
Thanks this is what I need.  I tried to apply it to my code but I didn't suceed yet, I'm trying to figure out what's wrong.

Code - C++: [Select]
  1. Autodesk.AutoCAD.Windows.Data.DataItemCollection ts = AcadApp.UIBindings.Collections.TextStyles;
  2. var bs = new BindingSource(ts, null);
  3. this.cbTest.DataSource = bs;
  4.  
  5.  

Here is the content of the combobox with this code :

ChrisCarlson

  • Guest

latour_g

  • Newt
  • Posts: 184
Re: Import text style, dim style, leader style drop down list from Autocad
« Reply #11 on: April 29, 2016, 09:20:58 AM »
No ! I have never use WPF.  Thanks for the link, I'm looking at it right now.

latour_g

  • Newt
  • Posts: 184
I've been working on this WPF things and I can't make it work correctly.

Here is what I've done so far.

1 - I have create a new user control (WPF) named listeAutocad.xaml
2 - I have declare Textstyle + binding it to my combobox (see image)
3 - I have create a Element host in my pallette but I get an error when trying to choose listeAutocad (see image)

MexicanCustard

  • Swamp Rat
  • Posts: 705
You're binding the ItemsSource to TextStyles.  Where are you defining TextStyles? 
Revit 2019, AMEP 2019 64bit Win 10

MexicanCustard

  • Swamp Rat
  • Posts: 705
Also, if you're just learning WPF I would recommend starting out with the MVVM architecture.  Easier to learn it first then to unlearn code behind and start using MVVM later.
Revit 2019, AMEP 2019 64bit Win 10

latour_g

  • Newt
  • Posts: 184
My mistake, I guess it should be more that :

ItemsSource="{Binding ts}"

Okay I will check that, thanks !

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Hi,

Here's a little sample which shows how this can be done with WPF and code behind.

The PaletteTab.xaml file:
- the combo box ItemsSource is bound to the Textstyles property (DataItemCollection) defined in the code behind and the display member is the Name of each item.
- each control is named to be used in the code behind
Code - XML: [Select]
  1. <UserControl x:Class="WpfUiBindingSample.PaletteTab"
  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:WpfUiBindingSample"
  7.             mc:Ignorable="d"
  8.             d:DesignHeight="300" d:DesignWidth="300">
  9.     <StackPanel Background="WhiteSmoke">
  10.         <ComboBox x:Name="cbxTextstyle" HorizontalAlignment="Stretch" Margin="20"
  11.                  ItemsSource="{Binding TextStyles}" DisplayMemberPath="Name"/>
  12.         <Button x:Name="btnDoIt" Content="DO IT" Width="80" Click="btnDoIt_Click"/>
  13.     </StackPanel>
  14. </UserControl>

The code behind, PaletteTab.xaml.cs file:
- the DataContext is set to this class where the TextStyles property is defined using UIBindings.Collections.TextStyles
- event handlers use control names
Code - C#: [Select]
  1. using Autodesk.AutoCAD.Windows.Data;
  2. using System.Collections.Specialized;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  6.  
  7. namespace WpfUiBindingSample
  8. {
  9.     public partial class PaletteTab : UserControl
  10.     {
  11.         public PaletteTab()
  12.         {
  13.             InitializeComponent();
  14.             DataContext = this;
  15.             cbxTextstyle.SelectedItem = TextStyles.CurrentItem;
  16.             TextStyles.CollectionChanged += TextStyles_CollectionChanged;
  17.         }
  18.  
  19.         public DataItemCollection TextStyles => AcAp.UIBindings.Collections.TextStyles;
  20.  
  21.         private void btnDoIt_Click(object sender, RoutedEventArgs e)
  22.         {
  23.             AcAp.ShowAlertDialog(((INamedValue)cbxTextstyle.SelectedItem).Name);
  24.         }
  25.  
  26.         private void TextStyles_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  27.         {
  28.             cbxTextstyle.SelectedItem = TextStyles.CurrentItem;
  29.         }
  30.     }
  31. }
Speaking English as a French Frog

Jeff H

  • Needs a day job
  • Posts: 6150

Good stuff and thanks everyone.I have never used those collections but is the control bounded to the Active Document textstyles, and does it update collection when switching documents?





gile

  • Gator
  • Posts: 2520
  • Marseille, France
@Jeff H,

Yes it is and yes it does.
DataItemCollection is an 'observable collection'.
« Last Edit: May 11, 2016, 09:48:59 AM by gile »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Here's the same little sample but using MVVM design pattern.
This may seem unnecessarily verbose and complex for such a simple task, but as the saying MexicanCustard, it is better to start directly with this architecture.

With MVVM, it takes full advantages of the Binding. It is not necessary to name the controls, they're simply bound to properties the ViewModel.
The XAML file:
Code - XML: [Select]
  1. <UserControl x:Class="MVVMUIBindingSample.View.PaletteTab"
  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:MVVMUIBindingSample.View"
  7.             mc:Ignorable="d"
  8.             d:DesignHeight="300" d:DesignWidth="300">
  9.     <StackPanel Background="WhiteSmoke">
  10.         <ComboBox HorizontalAlignment="Stretch" Margin="20"
  11.                  ItemsSource="{Binding TextStyles}" DisplayMemberPath="Name" SelectedItem="{Binding TextStyle}"/>
  12.         <Button Content="DO IT" Width="80" Command="{Binding DoItCommand}"/>
  13.     </StackPanel>
  14. </UserControl>

The code behind is nearly empty (except to set the DataContext to the ViewModel.
The .xaml.cs file:
Code - C#: [Select]
  1. using System.Windows.Controls;
  2.  
  3. namespace MVVMUIBindingSample.View
  4. {
  5.     public partial class PaletteTab : UserControl
  6.     {
  7.         public PaletteTab()
  8.         {
  9.             InitializeComponent();
  10.             DataContext = new ViewModel.PaletteTabViewModel();
  11.         }
  12.     }
  13. }

The ViewModel folder contains the PaletteTabViewModel class and two classical helper classes.
PaletteTabViewModel.cs file defines the properties the controls are bound to.
Code - C#: [Select]
  1. using Autodesk.AutoCAD.Windows.Data;
  2. using System.ComponentModel;
  3. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  4.  
  5. namespace MVVMUIBindingSample.ViewModel
  6. {
  7.     class PaletteTabViewModel : ObservableObject
  8.     {
  9.         ICustomTypeDescriptor descriptor;
  10.  
  11.         public PaletteTabViewModel()
  12.         {
  13.             TextStyle = TextStyles.CurrentItem;
  14.             TextStyles.CollectionChanged += (s, e) => TextStyle = TextStyles.CurrentItem;
  15.             DoItCommand = new RelayCommand((_) => DoIt(), (_) => descriptor != null);
  16.         }
  17.  
  18.         public DataItemCollection TextStyles => AcAp.UIBindings.Collections.TextStyles;
  19.  
  20.         public ICustomTypeDescriptor TextStyle
  21.         {
  22.             get { return descriptor; }
  23.             set { descriptor = value; RaisePropertyChanged(nameof(TextStyle)); }
  24.         }
  25.  
  26.         public RelayCommand DoItCommand { get; }
  27.  
  28.         private void DoIt() => AcAp.ShowAlertDialog(((INamedValue)descriptor).Name);
  29.     }
  30. }

The ObservableObject and RelayCommand classes are classical MVVM helpers used to implement the unavoidable INotifyPropertyChanged and ICommand interfaces (minimalist but usually sufficient implementations here).

Observableobject.cs
Code - C#: [Select]
  1. using System.ComponentModel;
  2.  
  3. namespace MVVMUIBindingSample.ViewModel
  4. {
  5.     class ObservableObject : INotifyPropertyChanged
  6.     {
  7.         public event PropertyChangedEventHandler PropertyChanged;
  8.  
  9.         protected void RaisePropertyChanged(string propertyName)
  10.         {
  11.             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  12.         }
  13.     }
  14. }

RelayCommand.cs
Code - C#: [Select]
  1. using System;
  2. using System.Windows.Input;
  3.  
  4. namespace MVVMUIBindingSample.ViewModel
  5. {
  6.     class RelayCommand : ICommand
  7.     {
  8.         readonly Action<object> execute;
  9.         readonly Predicate<object> canExecute;
  10.  
  11.         public RelayCommand(Action<object> execute, Predicate<object> canExecute)
  12.         {
  13.             this.execute = execute;
  14.             this.canExecute = canExecute;
  15.         }
  16.  
  17.         public void Execute(object parameter) => execute(parameter);
  18.  
  19.         public bool CanExecute(object parameter) => canExecute(parameter);
  20.  
  21.         public event EventHandler CanExecuteChanged
  22.         {
  23.             add { CommandManager.RequerySuggested += value; }
  24.             remove { CommandManager.RequerySuggested -= value; }
  25.         }
  26.     }
  27. }
Speaking English as a French Frog

latour_g

  • Newt
  • Posts: 184
Thanks Gile !

Jeff H

  • Needs a day job
  • Posts: 6150
Thanks gile!

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Hi,

Here's a WPF control which does the same as the Styles toolbar (plus the current layer).

the xaml code:
Code - XML: [Select]
  1. <UserControl x:Class="WpfUiBindingSample.AcadStylesControl"
  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:WpfUiBindingSample"
  7.             mc:Ignorable="d"
  8.             d:DesignHeight="270" d:DesignWidth="180">
  9.     <StackPanel Background="WhiteSmoke">
  10.         <Label>Layer:</Label>
  11.         <ComboBox HorizontalAlignment="Stretch" Margin="5,0,5,5"
  12.                  ItemsSource="{Binding Layers}" DisplayMemberPath="Name" SelectedItem="{Binding Clayer}"/>
  13.         <Label>Text Style:</Label>
  14.         <ComboBox HorizontalAlignment="Stretch" Margin="5,0,5,5"
  15.                  ItemsSource="{Binding TextStyles}" DisplayMemberPath="Name" SelectedItem="{Binding Textstyle}"/>
  16.         <Label>Dimension Style:</Label>
  17.         <ComboBox HorizontalAlignment="Stretch" Margin="5,0,5,5"
  18.                  ItemsSource="{Binding DimensionStyles}" DisplayMemberPath="Name" SelectedItem="{Binding Dimstyle}"/>
  19.         <Label>Table Style:</Label>
  20.         <ComboBox HorizontalAlignment="Stretch" Margin="5,0,5,5"
  21.                  ItemsSource="{Binding TableStyles}" DisplayMemberPath="Name" SelectedItem="{Binding Tablestyle}"/>
  22.         <Label>MLeader Style:</Label>
  23.         <ComboBox HorizontalAlignment="Stretch" Margin="5,0,5,10"
  24.                  ItemsSource="{Binding MleaderStyles}" DisplayMemberPath="Name" SelectedItem="{Binding MLeaderstyle}"/>
  25.     </StackPanel>
  26. </UserControl>
  27.  

the xaml.cs code behind:
Code - C#: [Select]
  1. using System.Windows.Controls;
  2.  
  3. namespace WpfUiBindingSample
  4. {
  5.     public partial class AcadStylesControl : UserControl
  6.     {
  7.         public AcadStylesControl()
  8.         {
  9.             InitializeComponent();
  10.             DataContext = new AcadStylesControlViewModel();
  11.         }
  12.     }
  13. }
  14.  

The ViewModel code (all the magic is here)
Some tricks:
- using Reflection allows to refactor the properties initialization in a single private method
- the properties bound to current items have the same name as the Database properties to get/set current styles
Code - C#: [Select]
  1. using Autodesk.AutoCAD.Windows.Data;
  2. using System.ComponentModel;
  3. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  4.  
  5. namespace WpfUiBindingSample
  6. {
  7.     class AcadStylesControlViewModel : INotifyPropertyChanged
  8.     {
  9.         // INotifyPropertyChanged implementation
  10.         public event PropertyChangedEventHandler PropertyChanged;
  11.  
  12.         protected void OnPropertyChanged(string propertyName)
  13.         {
  14.             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  15.         }
  16.  
  17.         // private fields
  18.         ICustomTypeDescriptor layer, textstyle, dimstyle, tablestyle, mleaderstyle;
  19.  
  20.         // constructor (initialization of current style properties)
  21.         public AcadStylesControlViewModel()
  22.         {
  23.             Initialize(nameof(Clayer), Layers);
  24.             Initialize(nameof(Textstyle), TextStyles);
  25.             Initialize(nameof(Dimstyle), DimensionStyles);
  26.             Initialize(nameof(Tablestyle), TableStyles);
  27.             Initialize(nameof(MLeaderstyle), MleaderStyles);
  28.         }
  29.  
  30.         // collection properties bound to AutoCAD via UIBindings
  31.         public DataItemCollection Layers => AcAp.UIBindings.Collections.Layers;
  32.  
  33.         public DataItemCollection TextStyles => AcAp.UIBindings.Collections.TextStyles;
  34.  
  35.         public DataItemCollection DimensionStyles => AcAp.UIBindings.Collections.DimensionStyles;
  36.  
  37.         public DataItemCollection TableStyles => AcAp.UIBindings.Collections.TableStyles;
  38.  
  39.         public DataItemCollection MleaderStyles => AcAp.UIBindings.Collections.MleaderStyles;
  40.  
  41.         // current setting properties (same names as Database properties)
  42.         public ICustomTypeDescriptor Clayer
  43.         {
  44.             get { return layer; }
  45.             set { SetCurrentValue(nameof(Clayer), ref layer, value); }
  46.         }
  47.  
  48.         public ICustomTypeDescriptor Textstyle
  49.         {
  50.             get { return textstyle; }
  51.             set { SetCurrentValue(nameof(Textstyle), ref textstyle, value); }
  52.         }
  53.  
  54.         public ICustomTypeDescriptor Dimstyle
  55.         {
  56.             get { return dimstyle; }
  57.             set { SetCurrentValue(nameof(Dimstyle), ref dimstyle, value); }
  58.         }
  59.  
  60.         public ICustomTypeDescriptor Tablestyle
  61.         {
  62.             get { return tablestyle; }
  63.             set { SetCurrentValue(nameof(Tablestyle), ref tablestyle, value); }
  64.         }
  65.  
  66.         public ICustomTypeDescriptor MLeaderstyle
  67.         {
  68.             get { return mleaderstyle; }
  69.             set { SetCurrentValue(nameof(MLeaderstyle), ref mleaderstyle, value); }
  70.         }
  71.  
  72.         // private methods (using of Reflection to work with properties names)
  73.         private void Initialize(string propName, DataItemCollection collection)
  74.         {
  75.             var curProp = GetType().GetProperty(propName);
  76.             curProp.SetValue(this, collection.CurrentItem, null);
  77.             collection.PropertyChanged += (s, e) =>
  78.             {
  79.                 if (e.PropertyName == nameof(collection.CurrentItem))
  80.                     curProp.SetValue(this, collection.CurrentItem, null);
  81.             };
  82.         }
  83.  
  84.         private void SetCurrentValue(string propName, ref ICustomTypeDescriptor descriptor, ICustomTypeDescriptor value)
  85.         {
  86.             if (value != null && (IDataItem)descriptor != (IDataItem)value)
  87.             {
  88.                 descriptor = value;
  89.                 OnPropertyChanged(propName);
  90.                 var doc = AcAp.DocumentManager.MdiActiveDocument;
  91.                 using (doc.LockDocument())
  92.                 {
  93.                     var db = doc.Database;
  94.                     db.GetType().GetProperty(propName).SetValue(db, ((IDataItem)value).ObjectId, null);
  95.                     doc.Editor.WriteMessage($"\n{propName} = {((INamedValue)value).Name}");
  96.                 }
  97.             }
  98.         }
  99.     }
  100. }
  101.  

A command to show the control in a palette
Code - C#: [Select]
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.Windows;
  3. using System;
  4. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  5.  
  6. [assembly: CommandClass(typeof(WpfUiBindingSample.Commands))]
  7.  
  8. namespace WpfUiBindingSample
  9. {
  10.     public class Commands
  11.     {
  12.         static PaletteSet palette;
  13.         static bool wasVisible;
  14.  
  15.         [CommandMethod("STYLES")]
  16.         public static void TestPaletteCommand()
  17.         {
  18.             if (palette == null)
  19.             {
  20.                 palette = new PaletteSet("Layer & Styles", "STYLES", new Guid("{3F1BEBD1-3005-412F-8D02-E6475EF5364F}"));
  21.                 palette.Style =
  22.                     PaletteSetStyles.ShowAutoHideButton |
  23.                     PaletteSetStyles.ShowCloseButton |
  24.                     PaletteSetStyles.ShowPropertiesMenu;
  25.                 palette.MinimumSize = new System.Drawing.Size(180, 275);
  26.                 palette.AddVisual("Styles", new AcadStylesControl());
  27.  
  28.                 var docs = AcAp.DocumentManager;
  29.                 docs.DocumentBecameCurrent += (s, e) => palette.Visible = e.Document == null ? false : wasVisible;
  30.                 docs.DocumentCreated += (s, e) => palette.Visible = wasVisible;
  31.                 docs.DocumentToBeDeactivated += (s, e) => wasVisible = palette.Visible;
  32.                 docs.DocumentToBeDestroyed += (s, e) =>
  33.                 {
  34.                     wasVisible = palette.Visible;
  35.                     if (docs.Count == 1)
  36.                         palette.Visible = false;
  37.                 };
  38.             }
  39.             palette.Visible = true;
  40.         }
  41.     }
  42. }
  43.  
« Last Edit: July 26, 2016, 11:40:39 AM by gile »
Speaking English as a French Frog