DateRangeFilterAction for WIN - XAF
Sometimes it is necessary to create a custom action, like an action that accepts two parameters (a DateTime range).
To create a DateTime Range the best approach is to create a custom Action with a custom ActionItem
public class DateRangeFilterActionBarItem : BarActionBaseItem
{
RepositoryItemDateEdit repositoryItem1;
RepositoryItemDateEdit repositoryItem2;
BarEditItem newBarDateFrom;
BarEditItem newBarDateTo;
DateTime time1 =new DateTime( DateTime.Today.Year,DateTime.Today.Month, 1) ;
DateTime time2 = DateTime.Today;
public DateRangeFilterActionBarItem(ActionBase action, BarManager manager) : base(action, manager) { }
protected override BarItem CreateControlCore()
{
BarButtonGroup group = new BarButtonGroup(Manager);
repositoryItem1 = new RepositoryItemDateEdit();
repositoryItem1.Name = "From";
repositoryItem1.Mask.UseMaskAsDisplayFormat = true;
repositoryItem2 = new RepositoryItemDateEdit();
repositoryItem2.Mask.UseMaskAsDisplayFormat = true;
repositoryItem1.Name = "To";
repositoryItem1.EditValueChanged += repositoryItem1_EditValueChanged;
repositoryItem2.EditValueChanged += repositoryItem2_EditValueChanged;
newBarDateFrom = new BarEditItem(Manager, repositoryItem1);
newBarDateFrom.Caption = "Fecha: ";
newBarDateFrom.EditValue = time1;
newBarDateFrom.Width = 100;
group.AddItem(newBarDateFrom);
newBarDateTo = new BarEditItem(Manager, repositoryItem2);
newBarDateTo.EditValue = time2;
newBarDateTo.Width = 100;
group.AddItem(newBarDateTo);
return group;
}
void repositoryItem1_EditValueChanged(object sender, EventArgs e)
{
time1 = ((DateEdit)sender).DateTime;
((DateRangeFilterAction)Action).DoExecute(time1, time2);
}
void repositoryItem2_EditValueChanged(object sender, EventArgs e)
{
time2 = ((DateEdit)sender).DateTime;
newBarComboItem.EditValue = "Personalizado";
((DateRangeFilterAction)Action).DoExecute(time1, time2);
}
}
When the form's menu is created, XAF creates action items for all actions placed to this form via action containers. This operation is performed by the BarActionItemsFactory. Since we have implemented a custom action type, it is required to implement a custom BarActionItemsFactory to assign an appropriate action item to actions of this type. The custom BarActionItemsFactory is registered via the custom factory provider (MyBarActionItemsFactoryProvider).
public class MyBarActionItemsFactory : BarActionItemsFactory
{
...
protected override BarActionBaseItem CreateActionItem(ActionBase action)
{
if (action is DateRangeFilterAction)
{
return new DateRangeFilterActionBarItem(action, Manager);
}
return base.CreateActionItem(action);
}
}
public class MyBarActionItemsFactoryProvider : IBarActionItemsFactoryProvider
{
public BarActionItemsFactory CreateBarActionItemsFactory(BarManager barManager)
{
return new MyBarActionItemsFactory(barManager);
}
}
And the BarActionItemsFactoryProvider.Instance must be set in the Module.
public sealed partial class MyModuleWin : ModuleBase
{
public DateRangeFilter for WIN - XAF()
{
InitializeComponent();
BarActionItemsFactoryProvider.Instance = new MyBarActionItemsFactoryProvider();
}
......
}
So far this is similar to the sample provided by DevExpress:How to create custom action type with custom control (BarCheckItem),associated with it
But with a DateRange we want to pass 2 parameters in the DoExecute method, so the ListView can be filtered by this parameters.
The SimpleAction class does not contain the DoExecute method with two parameters, that's why there is a need to implement my own method:
public class ActionDateRangeEventArgs : ActionBaseEventArgs
{
DateTime from;
DateTime to;
public ActionDateRangeEventArgs(ActionBase action, DateTime _From, DateTime _To)
: base(action) {
from = _From;
to = _To;
}
public DateTime From {
get { return from; }
}
public DateTime To
{
get { return to; }
}
}
public delegate void DateRangeFilterActionExecuteEventHandler(Object sender, ActionDateRangeEventArgs e);
[DXToolboxItem(true)]
//[ToolboxBitmap(typeof(XafApplication), "Resources.Actions.Action_SimpleAction.bmp")]
[DevExpress.Utils.ToolboxTabName(XafAssemblyInfo.DXTabXafActions)]
public class DateRangeFilterAction : ActionBase {
public DateRangeFilterAction() : this(null) { }
public DateRangeFilterAction(IContainer container) : base(container) { }
public DateRangeFilterAction(Controller owner, string id, string category) : base(owner, id, category) { }
public DateRangeFilterAction(Controller owner, string id, PredefinedCategory category)
: this(owner, id, category.ToString()) { }
public DateRangeFilterAction(Controller owner, string id, string category, DateRangeFilterActionExecuteEventHandler execute)
: this(owner, id, category) {
Execute += execute;
}
public bool DoExecute(DateTime From, DateTime To)
{
return ExecuteCore(Execute, new ActionDateRangeEventArgs(this, From, To));
}
protected override void RaiseExecute(ActionBaseEventArgs eventArgs) {
Execute(this, (ActionDateRangeEventArgs)eventArgs);
}
/*
[
#if !SL
DevExpressExpressAppLocalizedDescription("DateRangeFilterActionExecuteEventHandler"),
#endif
Category("Action")]*/
[Category("Action")]
public event DateRangeFilterActionExecuteEventHandler Execute;
}
The next task is to write a controller that creates a DateRangeFilterAction that filters the ListView based on From-To Date Range:
public partial class DateRageFilterController : ViewController
{
public DateRageFilterController()
{
InitializeComponent();
RegisterActions(components);
TargetViewType = ViewType.ListView;
TargetViewNesting = Nesting.Root;
DateRangeFilterAction action = new DateRangeFilterAction(this, "DateRangeAction", PredefinedCategory.RecordEdit);
action.Execute += actionDateRange_Execute;
}
protected override void OnViewControlsCreated()
{
base.OnViewControlsCreated();
FilterData(DateTime.Today, DateTime.Today);
}
void actionDateRange_Execute(object sender, ActionDateRangeEventArgs e)
{
FilterData(e.From, e.To);
}
void FilterData(DateTime From, DateTime To) {
CriteriaOperator criterion = null;
criterion = CriteriaOperator.Parse("CreatedOn >= ? and CreatedOn <= ?", From, To);
((ListView)View).CollectionSource.Criteria["DateRangeFilter"] = criterion;
}
}
Full code is avalaible at:
http://www.devexpress.com/Support/Center/Question/Details/T111170
What's next? An improvement would be a Node at the ListView that contains the field that will be used in the criteria for the ListView Filtering.
I'll write about this in my next blog.
Analia Urbano
www.analiaurbano.com.ar
https://www.linkedin.com/pub/analia-urbano-gonzalez/19/a12/92a