При необходимости в фильтр списковых форм можно добавить помимо стандартных (доступных для выбора через форму подбора колонок, вызываемую по нажатию клавиши ) дополнительные свойства и/или логику.
Сделать это, однако, можно только для пользовательских (кастомизированных) списковых форм, но не для форм, генерируемых системой по умолчанию. Это ограничение легко обойти, создав в несколько простых шагов пользовательскую копию списковой формы. Например, для плоского справочника достаточно создать новый объект Windows Form, унаследовать его от BaseFlatDictionaryListForm и реализовать интерфейсы IRecordBrowser<T> и IRecordSelector<T>, где Т – тип справочника (подробно процесс описан на начальном этапе создания Списковой формы справочника):
public partial class ArticleListForm : BaseFlatDictionaryListForm, IRecordBrowser<Article>, IRecordSelector<Article> { public ArticleListForm() { InitializeComponent(); } } |
Добавить свое свойство в фильтр списковой формы можно двумя способами:
1.добавить одно или несколько дополнительных свойств в Пользовательский фильтр. Добавленные таким образом свойства будут изначально доступны всем пользователям. При настройке Пользовательского фильтра через форму подбора колонок, вызываемую по нажатию клавиши , их нельзя будет удалить;
2.настроить с нуля Стандартный фильтр, добавив туда требуемые свойства и, при необходимости, стандартные (все или выборочно).
Рассмотрим оба варианта на примере списковой формы справочника Articles. При этом для простоты примера добавим в фильтр не какую-либо сложную логику, а свойство самого справочника.
Для первого примера добавим в Пользовательский фильтр свойство Name. Для этого достаточно реализовать в классе списковой формы следующую логику:
public ArticleListForm() { InitializeComponent();
AddAdditionalFilterControls(); }
// Элемент управления, в котором будет вводиться текст фильтра private TextEdit ArticleNameFilterEdit { get; set; }
private void AddAdditionalFilterControls() { // Подпись к полю ввода фильтра var ArticleNameFilterLable = new LabelControl { Text = "Name", Dock = DockStyle.Top };
// Элемент управления – поле ввода фильтра ArticleNameFilterEdit = new TextEdit { Name = "ArticleNameFilterEdit", Dock = DockStyle.Top };
// Добавляем подпись и поле ввода в фильтр GridPanel.FilterControl.AdditionalFilterControls.Add(ArticleNameFilterLable); GridPanel.FilterControl.AdditionalFilterControls.Add(ArticleNameFilterEdit); ArticleNameFilterEdit.BringToFront(); GridPanel.FilterControl.BestSizeAdditionalFilterControls(); }
// Применяем фильтр private void GridPanel_ApplyCustomFilter(object sender, CustomFilterEventArgs args) { if (args.FilterActive && !string.IsNullOrWhiteSpace(ArticleNameFilterEdit.Text)) { var name = ArticleNameFilterEdit.Text;
args.AddFilter<Article>(a => a.name.ToLower().Contains(name)); } } |
Второй пример предполагает создание нового элемента управления для Стандартного фильтра. Создаем новый элемент User control, наследуем его от CommonControl (из пространства имен Ultima.Client) и реализуем интерфейс ICompositeFilterControl (из пространства имен Ultima.Client.Controls.Filtering):
public partial class MyFilterControl : CommonControl, ICompositeFilterControl { public MyFilterControl() { InitializeComponent(); } } |
Реализуем интерфейсы ICompositeFilterControl:
public partial class MyFilterControl : CommonControl, ICompositeFilterControl { public MyFilterControl() { InitializeComponent(); }
public event EventHandler ApplyFilters;
public ClassDescriptors.IClassDescriptor ClassDescriptor { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
public event EventHandler FilterExpressionChanged;
public Task<System.Linq.Expressions.LambdaExpression> GetFilterExpressionAsync() { throw new NotImplementedException(); }
public void ResetFilter() { throw new NotImplementedException(); }
public void ShowCustomizationForm() { throw new NotImplementedException(); }
public bool SupportsCustomization { get { throw new NotImplementedException(); } } } |
Размещаем на фильтре элементы управления, посредством которых будет осуществлять ввод значений фильтра – Name, State и Brand:
Реализуем логику фильтра:
public partial class MyFilterControl : CommonControl, ICompositeFilterControl { public MyFilterControl() { InitializeComponent(); }
public event EventHandler ApplyFilters;
// Заглушка для события ApplyFilters private void OnApplyFilters() { ApplyFilters.SafeInvoke(this, EventArgs.Empty); }
public event EventHandler FilterExpressionChanged;
// Заглушка для события ApplyFilters private void OnFilterExpressionChanged() { FilterExpressionChanged.SafeInvoke(this, EventArgs.Empty); }
// В дескрипторе класса указываем наш справочник public ClassDescriptors.IClassDescriptor ClassDescriptor { get { return Article.StaticClassDescriptor; } set { /* ignore */ } }
// Применяем фильтр public async Task<System.Linq.Expressions.LambdaExpression> GetFilterExpressionAsync() { // Объект фильтра var filter = PredicateBuilder.Get<Article>();
// И условия фильтра if (!string.IsNullOrWhiteSpace(NameEdit.Text)) { var name = NameEdit.Text; filter = filter.And(a => a.Name.ToLower().Contains(name.ToLower())); }
if (StateEdit.SelectedList.Any()) { var stateList = StateEdit.SelectedList; filter = filter.And(a => stateList.Contains(a.StateID)); }
if (BrandEdit.SelectedList.Any()) { var brandList = BrandEdit.SelectedList; filter = filter.And(a => brandList.Contains(a.BrandID)); }
return await Task.FromResult(filter); }
// Сбрасываем значения фильтра public void ResetFilter() { NameEdit.ResetText(); StateEdit.ClearSelectedRecords(); BrandEdit.ClearSelectedRecords(); }
public void ShowCustomizationForm() { throw new NotImplementedException(); }
// Запрещаем настройку фильтра стандартными средствами кастомизации public bool SupportsCustomization { get { return false; } } } |
И, наконец, остается указать в классе списковой формы справочника на необходимость использовать созданный фильтр:
public BaseArticleListForm() { InitializeComponent();
GridPanel.DefaultFilterControl = new MyFilterControl(); } |
По завершении компилируем проект, копируем созданные библиотеки в папку модуля в клиентском приложении Client/ClientModules/TradeTestSolution, перезагружаем метаданные и открываем фильтр списковой формы справочника Articles: •поле Name, добавленное первым способом в Пользовательский фильтр (User filter), отображается в верхней части фильтра; •поля, добавленные вторым способом в Стандартный фильтр (Default filter), отображаются в нижней его части. |