TheSwamp

Code Red => .NET => Topic started by: latour_g on April 27, 2016, 02:46:29 PM

Title: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g on April 27, 2016, 02:46:29 PM
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
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: lamarn on April 27, 2016, 03:00:34 PM
Maybe You should take a look at Lee Mac Steal from drawing/ template command..
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g on April 27, 2016, 03:11:09 PM
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.
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: ChrisCarlson on April 27, 2016, 03:28:13 PM
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);
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g on April 27, 2016, 03:53:22 PM
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 !
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: MexicanCustard on April 28, 2016, 07:56:35 AM
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.
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: ChrisCarlson on April 28, 2016, 09:09:16 AM
Potentially?

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

Code - Text: [Select]
  1. <ComboBox ItemsSource="{Binding TextStyles}">
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: MSTG007 on April 28, 2016, 03:09:42 PM
How did you get your tool palette to look like that? That's cool. Mine are just basic icon with text next to them.
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: ChrisCarlson on April 28, 2016, 04:09:17 PM
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.
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g on April 29, 2016, 08:57:24 AM
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 :
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: ChrisCarlson on April 29, 2016, 09:14:50 AM
Do you have your pallete setup to allow WPF content?

http://through-the-interface.typepad.com/through_the_interface/2009/08/hosting-wpf-content-inside-an-autocad-palette.html
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g 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.
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g on May 10, 2016, 11:01:15 AM
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)
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: MexicanCustard on May 10, 2016, 01:21:17 PM
You're binding the ItemsSource to TextStyles.  Where are you defining TextStyles? 
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: MexicanCustard on May 10, 2016, 01:23:07 PM
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.
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g on May 10, 2016, 01:27:28 PM
My mistake, I guess it should be more that :

ItemsSource="{Binding ts}"

Okay I will check that, thanks !
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: gile on May 11, 2016, 09:01:38 AM
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. }
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: Jeff H on May 11, 2016, 09:41:07 AM

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?




Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: gile on May 11, 2016, 09:43:35 AM
@Jeff H,

Yes it is and yes it does.
DataItemCollection is an 'observable collection'.
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: gile on May 11, 2016, 09:44:27 AM
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. }
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: latour_g on May 11, 2016, 09:50:16 AM
Thanks Gile !
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: Jeff H on May 11, 2016, 03:28:14 PM
Thanks gile!
Title: Re: Import text style, dim style, leader style drop down list from Autocad
Post by: gile on July 26, 2016, 08:59:17 AM
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.