Инструменты пользователя

Инструменты сайта


developers:tutorial:dlgandpropertygrid

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
developers:tutorial:dlgandpropertygrid [2019/02/10 17:50]
vasya
developers:tutorial:dlgandpropertygrid [2022/03/15 19:13] (текущий)
proxor
Строка 54: Строка 54:
  
 Отображение свойств в таблице настраивается с помощью разнообразных атрибутов,​ наследованных от [[developers:​references:​topomatic.componentmodel.propertytypeconverter|PropertyTypeConverter]],​ [[developers:​references:​topomatic.componentmodel.propertyeditor|PropertyEditor]] и [[developers:​references:​topomatic.componentmodel.propertyprovider|PropertyProvider]]. Более подробно они описаны в других разделах [[developers:​tutorial:​start|Руководства]]. ​ Отображение свойств в таблице настраивается с помощью разнообразных атрибутов,​ наследованных от [[developers:​references:​topomatic.componentmodel.propertytypeconverter|PropertyTypeConverter]],​ [[developers:​references:​topomatic.componentmodel.propertyeditor|PropertyEditor]] и [[developers:​references:​topomatic.componentmodel.propertyprovider|PropertyProvider]]. Более подробно они описаны в других разделах [[developers:​tutorial:​start|Руководства]]. ​
-Например, для отображения перечисления в виде выпадающего списка,​ необходимо написать наследника от [[developers:​references:​topomatic.componentmodel.baseenumconverter|BaseEnumConverter]]. В котором установить соответствие между значениями перечисления и строками используя свойство **Dictionary**. А затем назначить его на нужное свойство используя атрибут [[developers:​references:​topomatic.componentmodel.propertytypeconverterattribute|[PropertyTypeConverter]]].+В частности, для отображения перечисления в виде выпадающего списка,​ необходимо написать наследника от [[developers:​references:​topomatic.componentmodel.baseenumconverter|BaseEnumConverter]]. В котором установить соответствие между значениями перечисления и строками используя свойство **Dictionary**. А затем назначить его на нужное свойство используя атрибут [[developers:​references:​topomatic.componentmodel.propertytypeconverterattribute|[PropertyTypeConverter]]].
  
 +Создайте и настройте новый [[developers:​tutorial:​module|модуль]] для подключения к программному комплексу [[http://​www.topomatic.ru|Топоматик Робур]]. ​
  
 +С помощью диалогового окна Менеджер ссылок добавьте ссылки на следующие библиотеки:​
 +
 +  * [[developers:​references:​topomatic.cad.foundation|Topomatic.Cad.Foundation.dll]] - базовые математические типы и операции
 +  * [[developers:​references:​topomatic.cad.view|Topomatic.Cad.View.dll]] - элемент управления для отображения слоёв моделей
 +  * [[developers:​references:​topomatic.componentmodel|Topomatic.ComponentModel.dll]] - компоненты используемые для инспектирования свойств объектов
 +  * [[developers:​references:​topomatic.controls|Topomatic.Controls.dll]] - базовые диалоги и таблицы
 +  * [[developers:​references:​topomatic.alg.runtime|Topomatic.Alg.Runtime.dll]] - возможность использования класса [[developers:​references:​topomatic.alg.runtime.wrappers.simplechangetrackingwrapper|SimpleChangeTrackingWrapper]]
 +
 +<​note>​Не забудьте поставить флаг «Копировать локально» в «False». Кроме того, необходимо добавить нужные пространства имен в секцию using. Visual Studio позволяет легко сделать это, нажав правой клавишей на имени класса и выбрав добавление директивы using.</​note>​
 +
 +Создайте новый класс, назовите его TableWrapper.cs и разместите в нём реализацию таблицы.
 +<code csharp>
 +    //​Перечисление из нескольких значений
 +    enum DataEnum
 +    {
 +        Value1,
 +        Value2,
 +        Value3
 +    }
 +
 +    //​Структура данных,​ которая будет хранится в нашей модели
 +    struct DataValue
 +    {
 +        public double Length;
 +
 +        public string TextValue;
 +
 +        public DataEnum Value;
 +    }
 +
 +    //​Конвертер перечисления DataEnum в строковое представление и обратно
 +    class DataEnumConverter : BaseEnumConverter
 +    {
 +        public DataEnumConverter()
 +        {
 +            Dictionary[DataEnum.Value1] = "​Значение1";​
 +            Dictionary[DataEnum.Value2] = "​Значение2";​
 +            Dictionary[DataEnum.Value3] = "​Значение3";​
 +        }
 +    }
 +
 +    //​Класс реализующий обработку содержимого таблицы
 +    //Для простоты реализации,​ наследуем его от SimpleChangeTrackingWrapper
 +    class TableWrapper : SimpleChangeTrackingWrapper,​ IActivator
 +    {
 +        //​класс реализующий представление строки таблицы
 +        public class TableRow
 +        {
 +            //​Указатель на нашу таблицу,​ необходим,​ чтобы при изменении свойств выставить св-во IsChanged ​
 +            private SimpleChangeTrackingWrapper m_Wrapper;
 +
 +            private double m_Length;
 +
 +            private string m_TextValue;​
 +
 +            private DataEnum m_Value;
 +
 +            public TableRow(SimpleChangeTrackingWrapper wrapper, DataValue value)
 +            {
 +                m_Wrapper = wrapper;
 +                m_Length = value.Length;​
 +                m_TextValue = value.TextValue;​
 +                m_Value = value.Value;​
 +            }
 +
 +            //​Свойство длина
 +            //​Обратите внимание,​ что оно декорировано атрибутом Length - который позволяет выводить содержимое с точностью длин
 +            [DisplayName("​Длина,​ м"), Category("​Верхний заголовок|Нижний заголовок"​),​ Length]
 +            public double Length
 +            {
 +                get
 +                {
 +                    return m_Length;
 +                }
 +                set
 +                {
 +                    m_Length = value;
 +                    //​Предупреждаем таблицу,​ о наличии изменений
 +                    m_Wrapper.IsChanged = true;
 +                }
 +            }
 +
 +            //​Стоковое свойство
 +            [DisplayName("​Строка"​),​ Category("​Верхний заголовок|Нижний заголовок"​)]
 +            public string TextValue
 +            {
 +                get
 +                {
 +                    return m_TextValue;​
 +                }
 +                set
 +                {
 +                    m_TextValue = value;
 +                    //​Предупреждаем таблицу,​ о наличии изменений
 +                    m_Wrapper.IsChanged = true;
 +                }
 +            }
 +
 +            //​Свойство перечисление
 +            [DisplayName("​Перечисление"​),​ Category("​Верхний заголовок|Другой заголовок"​)]
 +            //Наш конвертер назначен с помощью атрибута PropertyTypeonverterAttribute
 +            [PropertyTypeConverter(typeof(DataEnumConverter))]
 +            public DataEnum Value
 +            {
 +                get
 +                {
 +                    return m_Value;
 +                }
 +                set
 +                {
 +                    m_Value = value;
 +                    //​Предупреждаем таблицу,​ о наличии изменений
 +                    m_Wrapper.IsChanged = true;
 +                }
 +            }
 +        }
 +
 +        //​Сохраняем ссылку на данные модели
 +        private List<​DataValue>​ m_Data;
 +
 +        //При создании таблицы,​ заполняем её содержимое данными из модели
 +        public TableWrapper(List<​DataValue>​ data)
 +        {
 +            m_Data = data;
 +            this.Items = new List<​object>​(m_Data.Count);​
 +            for (int i = 0; i < m_Data.Count;​ i++)
 +            {
 +                this.Items.Add(new TableRow(this,​ m_Data[i]));​
 +            }
 +        }
 +
 +        //​Считаем что наша таблица всегда доступна для редактирования
 +        public override bool IsReadOnly
 +        {
 +            get
 +            {
 +                return false;
 +            }
 +        }
 +
 +        //При вызове метода заполняем модель по даннм нашей таблицы
 +        public override void AcceptChanges()
 +        {
 +            m_Data.Clear();​
 +            for (int i = 0; i < this.Items.Count;​ i++)
 +            {
 +                var row = (TableRow)this.Items[i];​
 +                m_Data.Add(new DataValue() { Length = row.Length, TextValue = row.TextValue,​ Value = row.Value });
 +            }
 +        }
 +
 +        //​Реализация интерфеса IActivator
 +
 +        //​Всегда можем создавать экземпляр строки таблицы
 +        public bool CanCreateInstance
 +        {
 +            get
 +            {
 +                return true;
 +            }
 +        }
 +
 +        //​Создаем новый экземпляр строки таблицы
 +        public object CreateInstance()
 +        {
 +            return new TableRow(this,​ new DataValue());​
 +        }
 +    }
 +</​code>​
 +
 +<​note>​Обратите внимание,​ что свойство **Length** в строке таблицы декорировано атрибутом [[developers:​references:​topomatic.cad.foundation.design.lengthattribute|Length]]. Большая часть атрибутов реализованных в сборках программного комплекса,​ реализованы в пространствах имен **Design**</​note>​
 +
 +Теперь напишем реализацию диалога. Для этого добавьте в проект новую форму и назовите её TestSimpleDialog.
 +
 +{{ :​developers:​tutorial:​dlgandpropertygrid:​create_form.png?​direct&​600 |}}
 +
 +Откройте окно редактора кода, и сделайте её наследником от [[developers:​references:​topomatic.controls.dialogs.simpledlg|Topomatic.Controls.Dialogs.SimpleDlg]]. Затем добавьте на форму обычную панель и откройте код дизайнера в файле TestSimpleDialog.Designer.cs
 +
 +{{ :​developers:​tutorial:​dlgandpropertygrid:​add_panel.png?​direct&​600 |}}
 +
 +Замените класс панели **panel1** на [[developers:​references:​topomatic.controls.dialogs.edittableframe|EditTableFrame]] вручную и сохраните файл.
 +Теперь вернитесь в окно дизайнера и разместите [[developers:​references:​topomatic.controls.dialogs.edittableframe|EditTableFrame]] на диалоге. После чего оформите код диалога следующим образом:​
 +<code csharp>
 +    //​Наследуем наш диалог от Topomatic.Controls.Dialogs.SimpleDlg
 +    partial class TestSimpleDialog : Topomatic.Controls.Dialogs.SimpleDlg
 +    {
 +        public TestSimpleDialog()
 +        {
 +            InitializeComponent();​
 +        }
 +
 +        protected override void DoInit()
 +        {
 +            base.DoInit();​
 +            //на инициализации нам не нужно ничего делать
 +        }
 +
 +        protected override bool DoCommit()
 +        {
 +            var wrapper = (TableWrapper)panel1.Wrapper;​
 +            //при нажатии ОК проверяем,​ были ли изменения в таблице
 +            if (wrapper.IsChanged)
 +                //Если были, то заполняем данные модели
 +                wrapper.AcceptChanges();​
 +            return base.DoCommit();​
 +        }
 +
 +        //Для удобства использования реализуем статический метод, который принимает данные и показывает диалог
 +        public static bool Execute(List<​DataValue>​ values)
 +        {
 +            using (var dlg = new TestSimpleDialog())
 +            {
 +                //из-за особенностей реализации необходимо инициализировать фрэйм до вызова ShowDialog()
 +                dlg.panel1.Wrapper = new TableWrapper(values);​
 +                return dlg.ShowDialog() == DialogResult.OK;​
 +            }
 +        }
 +    }
 +</​code>​
 +
 +В теле программного модуля объявите команду "​test_dlg_and_table",​ и декорируйте её атрибутом "​cmd"​.
 +<code csharp>
 +    partial class Module : Topomatic.ApplicationPlatform.Plugins.PluginInitializator
 +    {
 +        //​Используем статический список для хранения наших данных в качестве модели
 +        private static List<​DataValue>​ m_Values = new List<​DataValue>​();​
 +
 +        [cmd("​test_dlg_and_table"​)]
 +        public void TestDlgAndTable()
 +        {
 +            //​Просто вызываем метод у нашего диалога
 +            TestSimpleDialog.Execute(m_Values);​
 +        }
 +    }
 +</​code>​
 +
 +Задача команды "​test_dlg_and_table"​ показать диалог редактирования данных,​ которые хранятся в статическом списке **m_Values** и дать возможность их редактировать в виде таблицы.
 +
 +Теперь необходимо сформировать наш файл .plugin. Заполните его следующим образом.
 +<code javascript>​
 +{
 +  "​assemblies":​ {
 +    "​tutorial5":​ {
 +      "​assembly":​ "​tutorial5.dll,​ tutorial5.ModulePluginHost"​
 +    }
 +  },
 +  "​actions":​ {
 +    "​id_test_dlg_and_table":​ {
 +      "​cmd":​ "​test_dlg_and_table",​
 +      "​title":​ "​Диалог и таблица"​
 +    }
 +  },
 +  "​menubars":​ {
 +    "​rbproj":​ {
 +      "​items":​ [
 +        {
 +          "​id":​ "​test_menu",​
 +          "​title":​ "​Примеры"​
 +        }
 +      ]
 +    },
 +    "​rbproj.test_menu":​ {
 +      "​items":​ [
 +        "​id_test_dlg_and_table"​
 +      ]
 +    }
 +  }
 +}
 +</​code>​
 +
 +Здесь мы описываем [[developers:​references:​core.plugin:​actions|actions]] для нашей команды,​ и добавляем пункт в меню.
 +Результатом запуска проекта будет появления в главном меню пункта «Примеры»,​ с подпунктом "​Диалог и таблица",​ который будет работать в соответствии с описанным выше алгоритмом. После запуска и выполнения мы увидим следующий результат:​
 +
 +{{ :​developers:​tutorial:​dlgandpropertygrid:​result.png?​direct&​600 |}}
 +
 +<​note>​[[developers:​tutorial:​tutorialcode|Исходный код]] примера расположен в проекте **"​tutorial5"​**.</​note>​
developers/tutorial/dlgandpropertygrid.1549821020.txt.gz · Последние изменения: 2021/07/22 14:28 (внешнее изменение)