Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: nolte от 31-01-2016, 22:17:44

Название: передача значений переменных из проекта WPF
Отправлено: nolte от 31-01-2016, 22:17:44
есть тестовое окно WPF при нажатии на кнопку TEXBLOCK получает некоторое значение (45 к примеру) непонятка состоит в том как из проекта WPF передать значение переменной (в данном случае "jj") в плагин для автокада. со всей ответственностью понимаю, что вопрос в общем то базовый но честно рыл просторы(это для любителей ответов типа " А что гугль в вашей деревне не работает") :)).
в WPF определяю переменную:
public string jj=textblk.Text;

в плагине пишу следующее
Код - C# [Выбрать]
  1. MainWindow _test = new MainWindow();
  2. _test.Show();
  3. string jjk = _test.jj;
  4. ed.WriteMessage("\nugol = " + jjk);
  5.  
запускаю. при вызове команды поднимается окно и в тоже време в командной строке, до нажатия на кнопки в окне, сообщение
ugol =
как бороться с безобразием подскажите


Название: Re: передача значений переменных из проекта WPF
Отправлено: Вильдар от 31-01-2016, 22:23:22
Попробуй форму запускать из автокадовского класса Application - в нем есть статические методы для показа окон модально/немодально.

Примера нет. На wpf пока не пишу.  :(
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 31-01-2016, 22:33:30
примерчик можно.
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 31-01-2016, 22:39:47
Во-первых - для вызова окон лучше использовать Autodesk.AutoCAD.ApplicationServices.Application.ShowModalWindow (ShowModelessWindow). Модальное окно блокирует основное окно автокада, а немодальное, соответственно не блокирует. Какое нужно вам - решаете сами
Как-то давно Андрей Бушман подсказал как более правильно открывать окна. Вот пример:
Код - C# [Выбрать]
  1. public class MpArmatureFunction
  2.     {
  3.         MpArmature _mpArmatureWin;
  4.         [CommandMethod("ModPlus", "mpArmature", CommandFlags.Modal)]
  5.         public void StartFunction()
  6.         {
  7.             if (_mpArmatureWin == null)
  8.             {
  9.                 _mpArmatureWin = new MpArmature { Separator = MpVars.MpSeparator };
  10.                 _mpArmatureWin.Closed += win_Closed;
  11.             }
  12.  
  13.             if (_mpArmatureWin.IsLoaded)
  14.                 _mpArmatureWin.Activate();
  15.             else
  16.                 AcApp.ShowModelessWindow(AcApp.MainWindow.Handle, _mpArmatureWin, false);
  17.         }
  18.         // Окно закрылось
  19.         void win_Closed(object sender, EventArgs e)
  20.         {
  21.             _mpArmatureWin = null;
  22.         }
  23.     }
Во-вторых - не понятно вы объясняете проблему, а значит и сами не совсем понимаете суть дела происходящего ))))
В-третьих - "проект WPF" и "плагин для автокада" - это неразделимые вещи

Объясните на примере, что вы хотите (например, "хочу окно. На нем кнопка. При нажатии происходит то-то"), а мы вам сделаем пример

P.S. При форматировании кода на форуме правильно выбирайте оформление - для C# нужно и выбирать C#
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Ривилис от 31-01-2016, 22:40:10
Application.ShowModalWindow и Application.ShowModelessWindow
P.S.: Посмотри у меня в подписи как форматировать код на форуме и исправь в своём сообщении.
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 31-01-2016, 23:24:50
задачка такова:
указать правильность открытия формы (было продемонстрированно) и как передать значение переменной в плагин. важен сам способ, по шаблону передать список тоже можно, важно знать как. для себя сделал простое окно и эксперементирую вот пока не пришел ни к чему по сему обратился на форум

Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 31-01-2016, 23:28:43
Вот набросал вам для примера:
Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

Проект тоже прикладываю.

Это как пример. Вариантов работы с окнами можно придумать больше. Да и всяких особенностей можете повстречать не мало. Но думаю для начала - вам сойдет для понимания и освоения
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 31-01-2016, 23:32:13
Александр Пекшев aka Modis,  огромное спасибо за помощь буду разбираться.
Название: Re: передача значений переменных из проекта WPF
Отправлено: Владимир Шу от 01-02-2016, 08:42:58
задачка такова:
указать правильность открытия формы (было продемонстрированно) и как передать значение переменной в плагин. важен сам способ, по шаблону передать список тоже можно, важно знать как. для себя сделал простое окно и эксперементирую вот пока не пришел ни к чему по сему обратился на форум
Пишем для AutoCAD и Civil 3D на C#.NET. Часть 11. Использование диалогов Windows Forms  (https://www.youtube.com/watch?v=qfQlgBdd2EU)
Пишем для AutoCAD и Civil 3D на C#.NET. Часть 11.1. Как передать данные в диалог Windows Forms  (https://www.youtube.com/watch?v=NN2JBxnEJ8E)
Пишем для AutoCAD и Civil 3D на C#.NET. Часть 12. Использование WPF диалогов. (https://www.youtube.com/watch?v=E4i7z35CLAw)
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 06-02-2016, 16:36:24
Boxa.Shu, Александр Пекшев aka Modis,
еще раз огромное спасибо все получилось видео толковое и понятное.
Текстбоксы и текстблоки работают на ура, комбобокс
временно отказывается, не передает ничего, кто-то подскажет как его побороть.



Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 06-02-2016, 18:16:32
комбобокс
временно отказывается, не передает ничего, кто-то подскажет как его побороть
Прикладывайте пример! Без примера сложно что-то сказать. В WPF элементы, имеющие items, могут содержать различные данные. Например можно в ComboBox забиндить свой класс, тогда и получать из него данные нужно по особенному. В общем - пример, пример, пример....

P.S. А еще не забывайте плюсовать карму и ставить в теме "решение", если оно есть. Нам так приятней  :)
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 06-02-2016, 22:16:47
второе сообщение не дает отметить как решение >:( .
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Ривилис от 06-02-2016, 22:22:41
второе сообщение не дает отметить как решение >:( .
Отмечать как "Решение" можно только одно сообщение в теме (ограничение движка). Плюсовать/минусовать можно любые сообщения.
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 07-02-2016, 18:31:38
доброго времени суток вот и пример
xaml
Извините, вам запрещён просмотр содержимого спойлеров.

xaml.cs
Извините, вам запрещён просмотр содержимого спойлеров.

дополнительный (связующий класс)
DtCombo.cs

Извините, вам запрещён просмотр содержимого спойлеров.

myPlugin.cs

Извините, вам запрещён просмотр содержимого спойлеров.
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 08-02-2016, 09:11:10
Ну раз никто не отвечает, то отвечу я) Visual Studio запускать не охота, поэтому буду так отвечать. Возможно где-то опечатаюсь)
1. Ну во-первых - это уже вопросы не данного форума. Это вопросы по чистому WPF - есть много других форумов хороших, где объяснят лучше
2. this.DataContext = data; - на мой взгляд вы полезли в дебри, которые вам (по опыту) вообще не пригодятся. DataContext для всего окна нужно использовать, когда у вас все окно будет "привязано" к определенному классу. И это касается не только данных, но и событий и прочего. Вам это не нужно
3. У вас два ComboBox - первый сделан правильно, второй - НЕТ! Поэтому и не работает. Чтобы использовать binding нужно для ComboBox задать ItemTemplate. Чтобы заполнить потом этот ComboBox, то нужно задать коллекцию для свойства ItemSource. В вашем случае должно быть так:
Код - XML [Выбрать]
  1. <ComboBox x:Name="CmbxFrom" Grid.Row="1" Margin="10">
  2.     <ComboBox.ItemTemplate>
  3.         <DataTemplate>
  4.             <TextBlock Text={Binding NameL}></TextBlock>
  5.         </DataTemplate>
  6.     </ComboBox.ItemTemplate>
  7. </ComboBox>
Ну и заполнение:
Код - C# [Выбрать]
  1. this.CmbxFrom.ItemSource = data;
Кстати, перед Name не обязательно писать x: - если честно, я даже не помню для чего это нужно))
4. UpdateSourceTrigger=PropertyChanged вам также не нужно. Это требуется обычно для двусторонней связи (еще нужно свойство Mode задать). Причем в этом случае в вашем классе DtCombo должна быть реализация PropertyChanged. По этому поводу можно много найти примеров в интернете. Но если вам ComboBox нужен только чтобы отобразить данные, без передачи обратно в класс (повторюсь - на практике для функций автокада этого достаточно), то всякие PropertyChanged и пр. вам не нужны
5. Чтобы потом написать в командную строку что выбрано в ComboBox, достаточно это ed.WriteMessage("\nCurrent layer :" + _dcombo.NameL); заменить на примерно это ed.WriteMessage("\nCurrent layer :" + _dcombo.CmbxFrom.SelectedItem.ToString());
В данном случае _dcombo.CmbxFrom.SelectedItem будет возвращать вам экземпляр класса DtCombo. Т.е. можете еще так сделать:
Код - C# [Выбрать]
  1. var selectedLayer = _dcombo.CmbxFrom.SelectedItem as DtCombo;
  2. d.WriteMessage("\nCurrent layer :" + selectedLayer.NameL);
6. Дальше смотреть не стал) Вы в проект запихиваете варианты из разных примеров, найденных в интернете - много лишнего) Старайтесь лишнего не писать/копировать - только запутаете
Название: Re: передача значений переменных из проекта WPF
Отправлено: Дмитрий Загорулькин от 08-02-2016, 11:28:24
2. this.DataContext = data; - на мой взгляд вы полезли в дебри, которые вам (по опыту) вообще не пригодятся. DataContext для всего окна нужно использовать, когда у вас все окно будет "привязано" к определенному классу. И это касается не только данных, но и событий и прочего. Вам это не нужно
Я, мягко говоря, не согласен с такой рекомендацией. Использование WPF без привязки данных не дает практически никаких преимуществ перед Windows Forms. Если "вам это не нужно", то пишите на Windows Forms. А если все-таки "вам это нужно", то читаем и изучаем концепцию MVVM (https://ru.wikipedia.org/wiki/Model-View-ViewModel)
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 08-02-2016, 11:33:30
Дмитрий Загорулькин, ты как-будто не прочитал, что я имел ввиду. DataContext для всего окна используется в паттерне MVVM - грубо говоря когда для всего окна разрабатывается специальный класс (View Model). В данном случае это все не нужно и достаточно привязки данных определенного класса к определенному элементу в окне
Название: Re: передача значений переменных из проекта WPF
Отправлено: Дмитрий Загорулькин от 08-02-2016, 11:57:04
Да, именно так и надо работать с WPF. И я не вижу причин, по которым именно этот случай является исключением. Товарищ nolte идет верным путем, но пока очень многого не понимает. Так не надо сбивать человека с него. Лучше сразу показывать как правильно делать а не учить неправильным вещам.
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 08-02-2016, 12:01:13
Дмитрий Загорулькин, вот мне нужно показать окно на котором будет всего один ComboBox со списком слоев. Чтобы его заполнить мне достаточно 4 строчки в xaml-разметке и еще пару строчек в коде. Ты предлагаешь для этого изучить и использовать паттерн MVVM, который требует не мало усилий и не мало кода. Зачем?
В любом случае - товарищу nolte информация для размышления предоставлена)
Название: Re: передача значений переменных из проекта WPF
Отправлено: Дмитрий Загорулькин от 08-02-2016, 12:08:29
который требует не мало усилий и не мало кода.
Вот в том-то и дело, что не требует он много кода и много усилий. В случае, когда всего один комбобокс на форме, никакого кода для ViewModel писать не надо. VM в этом случае - просто коллекция нужных объектов. Достаточно будет использовать одну из встроенных коллекций - массив, список и т.п.
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 08-02-2016, 12:25:37
VM в этом случае - просто коллекция нужных объектов. Достаточно будет использовать одну из встроенных коллекций - массив, список и т.п
Вот об этом и был мой ответ) И скорее всего товарищу nolte этого будет вполне достаточно
Лично мне вот MVVM пока никак не пригодился - я даже и не стал изучать/осваивать его
Название: Re: передача значений переменных из проекта WPF
Отправлено: Дмитрий Загорулькин от 08-02-2016, 12:56:29
доброго времени суток вот и пример
Если я правильно понял задумку, то я бы сделал как-то так:
Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.

Извините, вам запрещён просмотр содержимого спойлеров.
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 08-02-2016, 16:26:29
Вот спасибо, по-моему, мнение чайника  :), оба способа хороши попробую разобраться и с тем и с другим.
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 09-02-2016, 13:43:57
все классно, получилось работает как надо. с удовольствием налил бы подсказавшим ;D. будете в наших краях заходите :).
Название: Re: передача значений переменных из проекта WPF
Отправлено: Александр Пекшев aka Modis от 09-02-2016, 13:45:56
все классно, получилось работает как надо
Так по какому пути вы пошли? MVVM или обычный binding в ItemSource?
Название: Re: передача значений переменных из проекта WPF
Отправлено: nolte от 09-02-2016, 14:42:35
еще не пошел, но хорошо, что есть выбор. я так думаю, для не больших окон (2-3 переменные) подходит Ваш способ, ну а больше все же метод с дата файлом выглядит поприличней малеха. хотя все надо пощупать, попробовать на практике, протестить с опытом все взгляды меняются, как известно.
Название: Re: передача значений переменных из проекта WPF
Отправлено: alihovsky от 13-02-2023, 16:07:32
Приветствую.
Кто нибудь может оценить код?
Wpf окно с кнопки запрашивает центр круга, комбобокс собирает слои и назначает выбранный слой кругу, в текстбоксе радиус круга
Вопрос к спецам, нет здесь грубых ошибок? Код рабочий
Код - C# [Выбрать]
  1.  
  2. using System;
  3. using Autodesk.AutoCAD.Runtime;
  4. using AcApp = Autodesk.AutoCAD.ApplicationServices.Application;
  5.  
  6.  
  7. namespace WPFexample
  8. {
  9.     public class Class1
  10.     {
  11.  
  12.  
  13.         private static ModlessWindow _modlessWindow;
  14.         [CommandMethod("TestModless")]
  15.         public static void SecondExample()
  16.         {
  17.  
  18.  
  19.             if (_modlessWindow == null)
  20.             {
  21.                 _modlessWindow = new ModlessWindow();
  22.                 _modlessWindow.Closed += win_Closed;
  23.             }
  24.  
  25.  
  26.             if (_modlessWindow.IsLoaded)
  27.                 _modlessWindow.Activate();
  28.             else
  29.                 AcApp.ShowModelessWindow(AcApp.MainWindow.Handle, _modlessWindow, false);
  30.         }
  31.        
  32.         static void win_Closed(object sender, EventArgs e)
  33.         {
  34.             _modlessWindow = null;
  35.         }
  36.     }
  37. }
  38. using System.Windows;
  39. using System.Linq;
  40. using Autodesk.AutoCAD.ApplicationServices;
  41. using Autodesk.AutoCAD.DatabaseServices;
  42. using Autodesk.AutoCAD.EditorInput;
  43. using Autodesk.AutoCAD.Geometry;
  44. using Autodesk.AutoCAD.Windows.Data;
  45. using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
  46. using System.Windows.Input;
  47. using System;
  48.  
  49. namespace WPFexample
  50. {
  51.     /// <summary>
  52.     /// Логика взаимодействия для ModlessWindow.xaml
  53.     /// </summary>
  54.     public partial class ModlessWindow
  55.     {  
  56.         DataItemCollection my_layers;
  57.         public ModlessWindow()
  58.         {
  59.             InitializeComponent();
  60.             my_layers = AcAp.UIBindings.Collections.Layers;
  61.             //привязка данных слоя к ComboBox        
  62.             BindData();
  63.             // обновление ComboBox при изменении набора данных слоев
  64.             my_layers.CollectionChanged += (s, e) => BindData();
  65.         }
  66.  
  67.         private void BtAccept_OnClick(object sender, RoutedEventArgs e)
  68.         {            
  69.             {
  70.                 double my_radius;
  71.                 double.TryParse(TextBox.Text, out my_radius);
  72.                 var doc = AcAp.DocumentManager.MdiActiveDocument;
  73.                 if (doc != null)
  74.                 {
  75.                     // установить фокус на редактор AutoCAD                  
  76.                     AcAp.MainWindow.Focus();      
  77.                     using (doc.LockDocument())
  78.                     {
  79.                         DrawCircle(doc, my_radius, (string)cbxLayer.SelectedItem);
  80.                     }
  81.                 }
  82.             }
  83.         }
  84.  
  85.         private void DrawCircle(Document doc, double radius, string layer)
  86.         {
  87.             var db = doc.Database;
  88.             var ed = doc.Editor;
  89.             var ppr = ed.GetPoint("\nУкажите центр: ");
  90.             if (ppr.Status == PromptStatus.OK)
  91.             {
  92.                 using (var tr = db.TransactionManager.StartTransaction())
  93.                 {
  94.                     var curSpace =
  95.                         (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  96.                     using (var circle = new Circle(ppr.Value, Vector3d.ZAxis, radius))
  97.                     {
  98.                         circle.TransformBy(ed.CurrentUserCoordinateSystem);
  99.                         circle.Layer = layer;
  100.                         curSpace.AppendEntity(circle);
  101.                         tr.AddNewlyCreatedDBObject(circle, true);
  102.                     }
  103.                     tr.Commit();
  104.                 }
  105.             }
  106.         }
  107.  
  108.         private void BindData()
  109.         {
  110.             // привязка к источнику данных
  111.             // DataItemCollection преобразуется в массив имен слоев
  112.             cbxLayer.ItemsSource = my_layers.Select(x => ((INamedValue)x).Name).ToArray();
  113.             // выбор текущего слоя
  114.             cbxLayer.SelectedItem = ((INamedValue)my_layers.CurrentItem)?.Name;
  115.         }
  116.  
  117.         private void BtCancel_OnClick(object sender, RoutedEventArgs e)
  118.         {
  119.             Close();
  120.         }
  121.  
  122.         private void TextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
  123.         {
  124.         }
  125.  
  126. private void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
  127.         {
  128.             if (!(Char.IsDigit(e.Text, 0) || (e.Text == ".")
  129.                && (!TextBox.Text.Contains(".")
  130.                && TextBox.Text.Length != 0)))
  131.             {
  132.                 e.Handled = true;
  133.             }
  134.         }
  135.     }