Найти в Дзене

Создание WPF-приложения с DataGrid

Оглавление

В этой статье так же рассмотрим следующие темы:

  • Создание команды с параметром
  • Привязка с RelativeSource, изменение DataContext во вложенных объектах окна
  • Добавление SVG-иконок в окно.

Задача

Напишем простейший менеджер общих параметров. Он будет выводить таблицу с указанием Id и имени каждого общего параметра, и будет кнопка для удаления этого параметра.

Дисклеймер: Статья написана в учебных целях. Не надо брать и удалять все подряд общие параметры. Удалённый общий параметр пропадёт из всех семейств и спецификаций проекта, и его ручное добавление ничего не вернёт. Будьте аккуратны.

Решение

Я продолжу работать в своем проекте WPFApplication. Там используется Community.Toolkit.Mvvm. Как с ней работать, описано здесь. Если вам вообще непонятно, что происходит, читайте всю подборку про WPF.

Создам новую папку, и следующие файлы:

А также наконец-то добавлю Application и addin-файл, чтобы приложение можно было запустить с панели Ревита, а не через addin-менеджер.

Код ViewModel и Descriptor будет очень простым:

Дескриптор
Дескриптор
ВьюМодель
ВьюМодель

Обратите внимание, что тут мы передаём в команду параметр и даже типизируем его. Это важно, мы будем это использовать во View.

Окно

Самое интересное у нас будет в XAML-коде.

Я хочу сделать вот такое окно:

-4

Но как сделать кнопку с такой иконкой?

  • Найдём иконку в svg-формате.
  • Скачаем её и откроем в блокноте.
  • Скопируем в контент кнопки вот этот path и обернём его в xaml во ViewBox:
Код svg-картинки
Код svg-картинки

А в xaml поменяем path на Path и d на Data, и добавим цвет:

Xaml-код
Xaml-код

Готово, картинку добавили.

DataGrid

Теперь разберёмся с тем, как создать таблицу с данными. Тут нам поможет DataGrid. В принципе, нам даже не обязательно её заполнять колонками, а достаточно передать ItemSource, а колонки появятся сами по свойствам элементов, составляющих ItemSource. Но я предпочитаю явно указывать колонки. Получилось так:

-7

Мы создали 2 обычных текстовых колонки и одну колонку с кнопкой, переопределив её DataTemplate (мы уже разбирали что-то подобное). Переопределить шаблон можно так, как нам угодно — в данном случае мы сделали просто кнопку с картинкой, повесив на ней команду и передав Dexcriptor, являющийся контекстом данных строки, в качестве параметра.

Нюансы привязок и RelativeSourse

Теперь разберёмся, почему такие странные привязки в 25-27 строках. Дело в том, что когда мы попадаем внутрь элемента с ItemSource, контекстом данных для вложенных элементов становятся составляющие ItemSource объекты. То есть теперь для кнопки контекст данных — это SharedParameterDescriptor. И привязываемся мы непосредственно к нему, потому что мы передаём этот объект для удаления из коллекции параметров.

CommandParameter="{Binding }"

Зная это, мы понимаем, что теперь нельзя сослаться непосредственно на команду из ViewModel, так как мы прошли в ней глубже, и теперь нам надо сделать шаг назад. Поэтому пишем так:

Command="{Binding DataContext.DeleteParameterCommand,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">

То есть источник привязки мы ищем как вышестоящий относительно кнопки элемент (Ancestor), имеющий тип Window. Его DataContext — это наша ViewModel, так что так мы можем сослаться на команду из основной вьюМодели.

Тут сложно передать команду непосредственно в дескриптор. Да, мы сможем удалить параметр, но мы не сможем удалить его из коллекции параметров для View.

Заключение

В общем-то, всё. Мы получили работоспособный код (правда, в окне нет кнопки запуск, а параметр удаляется прям сразу по нажатию на кнопку, но и блог у меня не о UX/UI-дизайне плагинов). Посмотреть его и поэкспериментировать с ним можно как обычно, на GitHub.

И вновь напоминаю про свой телеграм-канал о Revit API. Заходите, подписывайтесь. До новых встреч!

-8