Осталось рассмотреть еще один вид фильтра: FunctionFilter (функция-фильтр).
В двух словах: вы можете написать С1 функцию (на C#), которая будет работать как фильтр для элементов заданного типа.
Рассмотрим пример.
У нас будут два простых глобальных типа данных:
- один будет использоваться для названий жанров кино (напр., фантастика, триллер и т.п.),
- другой будет использоваться для названий фильмов. Для фильмов мы также будем указывать год выпуска и жанры, к которым он относится.
Нюанс здесь заключается в том, что однозначно фильм отнести к одному-единственному жанру часто трудно и обычно указывают несколько жанров. Это означает, что один и тот же фильм должен появляться у нас в рамках нескольких жанров (групп).
Вот здесь нам и пригодится функция-фильтр. Итак,
- ...создадим тип данных для жанров - Demo.Genre - с одним полем: Name (строка, 64 символа). (Надпись, ярлык, можно указать на русском как "Название").
- также создадим тип данных для фильмов - Demo.Movie - с тремя полями:
- Title (строка, 64 символа) - ярлык: "Название"
- Year (целое число, или тоже строка) - ярлык: "Год"
- Genre (строка, неограниченная длина) - ярлык: "Жанр"
- Выберите это поле в редакторе типа данных.
- Перейдите на вкладку "Расширенные".
- Щелкните в "Типе виджета"
- Выберите и удалите виджет текстового поля (Composite.Widgets.String.TextBox)
- Добавьте виджет мульти-селектора идентификаторов данных (Composite.Widgets.String.DataIdMultiSelector)
- В функции виджета выберите параметер "Data type to select from" (т.е. тип данных для выбора элементов)
- И выберите для него наш типа данных жанра (Genre).
- Нажмите ОК и сохраните тип данных.
Для того, чтобы в нашем дереве что-то появилось, добавьте сразу несколько жанров и несколько фильмов. Обратите внимание, что при добавлении фильма у вас будут представлены жанры как опции и можно выбрать несколько жанров.
Создание функции-фильтра
Создание функции-фильтра
Теперь создадим функцию-фильтр. Проще всего создать встроенную C#-функцию прямо в админке (но можно создать и внешнюю C#-функцию и подключить ее в админке).
- В разделе "Функции", выбираем "C# функции" и нажимаем "Добавить встроенную C# функцию".
- В окне "Настройки" указываем:
- Название: IdListFilter
- Пространство имен: Demo
- Шаблон: Пустой
- В открывшемся редакторе функции, на вкладке "Код", удаляем код по умолчанию и заменяем на свой:
using System;
using System.Linq.Expressions;
namespace Demo
{
public static class InlineMethodFunction
{
public static Expression<Func<Demo.Movie, bool>> IdListFilter(Guid ParentId)
{
Expression<Func<Demo.Movie, bool>> filter = f => f.Genre.Contains(ParentId.ToString());
return filter;
}
}
}
- Теперь на вкладке "Входные параметры", добавляем параметр, указанный в нашем коде:
- Имя параметра: ParentId
- Тип параметра: Guid
- Сохраняем функцию.
Использование функции-фильтра
Чтобы теперь указать эту функцию в качестве фильтра для элементов данных в дереве:
- В XML-элементе DataElements, добавим знакомый нам Filters
- В нем добавим FunctionFilter
- И уже в FunctionFilter добавим нашу функцию, как обычно добавляется стандартная С1-функция в разметке.
<DataElements Type="Demo.Movie" Label="${C1:Data:Demo.Movie:Title} (${C1:Data:Demo.Movie:Year})">
<Filters>
<FunctionFilter>
<function name="Demo.IdListFilter" xmlns="http://www.composite.net/ns/function/1.0">
<param name="ParentId" value="${C1:Data:Demo.Genre:Id}"/>
</function>
</FunctionFilter>
</Filters>
</DataElements>
<Filters>
<FunctionFilter>
<function name="Demo.IdListFilter" xmlns="http://www.composite.net/ns/function/1.0">
<param name="ParentId" value="${C1:Data:Demo.Genre:Id}"/>
</function>
</FunctionFilter>
</Filters>
</DataElements>
Для функции мы соответственно указываем ее имя (name), а также параметр (param). В качестве значения параметра мы используем динамическое поле.
В конце концов у вас должно получится примерно такое определение дерева для консольного приложения:
<?xml version="1.0" encoding="utf-8" ?>
<ElementStructure xmlns="http://www.composite.net/ns/management/trees/treemarkup/1.0">
<ElementStructure.AutoAttachments>
<NamedParent Name="Content" Position="Top"/>
</ElementStructure.AutoAttachments>
<ElementRoot>
<Children>
<Element Id="MoviesRoot" Label="Фильмы">
<Children>
<DataElements Type="Demo.Genre" Icon="pagetype-pagetype-rootfolder">
<Children>
<DataElements Type="Demo.Movie" Icon="pagetype-pagetype" Label="${C1:Data:Demo.Movie:Title} (${C1:Data:Demo.Movie:Year})">
<Filters>
<FunctionFilter>
<function name="Demo.IdListFilter" xmlns="http://www.composite.net/ns/function/1.0">
<param name="ParentId" value="${C1:Data:Demo.Genre:Id}"/>
</function>
</FunctionFilter>
</Filters>
</DataElements>
</Children>
</DataElements>
</Children>
</Element>
</Children>
</ElementRoot>
</ElementStructure>
<ElementStructure xmlns="http://www.composite.net/ns/management/trees/treemarkup/1.0">
<ElementStructure.AutoAttachments>
<NamedParent Name="Content" Position="Top"/>
</ElementStructure.AutoAttachments>
<ElementRoot>
<Children>
<Element Id="MoviesRoot" Label="Фильмы">
<Children>
<DataElements Type="Demo.Genre" Icon="pagetype-pagetype-rootfolder">
<Children>
<DataElements Type="Demo.Movie" Icon="pagetype-pagetype" Label="${C1:Data:Demo.Movie:Title} (${C1:Data:Demo.Movie:Year})">
<Filters>
<FunctionFilter>
<function name="Demo.IdListFilter" xmlns="http://www.composite.net/ns/function/1.0">
<param name="ParentId" value="${C1:Data:Demo.Genre:Id}"/>
</function>
</FunctionFilter>
</Filters>
</DataElements>
</Children>
</DataElements>
</Children>
</Element>
</Children>
</ElementRoot>
</ElementStructure>
Заметьте, что в нем отсутствуют стандартные действия для добавления, редактирования и удаления элементов. Об этом я уже писал и вы сможете сделать это самостоятельно.
Ну и вы, наверняка, помните, что весь этот и подобный функционал можно упаковать в модуль расширения (т.е. экспортировать) и устанавливать на других сайтах на основе C1 (импортировать), распространяя его платно или бесплатно :)
(продолжение следует...)
Комментариев нет:
Отправить комментарий