I am trying to create a composite control consisting of the Business Pack DataPager and some other controls. The end goal is to have a single component similar to the following:
The BP DataPager will be the primary control in the new composite control. The new control needs a DataSet property for use by the DataPager and that DataSet needs to be the same object as the associated GridView’s DataSource property. (This would be the same as when you use the Business Pack GridView and the BP DataPager together.)
I have tried to piece together what to do from the instructions on the following three blog posts, but they do not seem to cover the more advanced (or maybe it’s basic) scenario I am facing:
- Part 1: Have you tried the new composite controls?
- Part 2: Have you tried the new composite controls?
- Using Composite Controls for the implementation of Bootstrap 5 components
No matter what I try, I cannot get the new control to work.
Here are two of the versions I have tried, neither of which work correctly:
Version 1
[ControlMarkupOptions(AllowContent = false)]
public class DataPagerAsCompositeControlV1 : CompositeControl
{
public static DotvvmControl GetContents
(
[MarkupOptions(Required = true)]
ValueOrBinding<IBusinessPackDataSet> dataSet
)
{
var bindingCompilationService = new BindingCompilationService(
new OptionsManager<BindingCompilationOptions>(new OptionsFactory<BindingCompilationOptions>(
new List<IConfigureOptions<BindingCompilationOptions>>(),
new List<IPostConfigureOptions<BindingCompilationOptions>>())),
new DefaultExpressionToDelegateCompiler(DotvvmConfiguration.CreateDefault()),
new DefaultDotvvmCacheAdapter());
return new HtmlGenericControl("div")
.AppendChildren
(
new DotVVM.BusinessPack.Controls.DataPager(new DotVVM.Framework.Controls.DataPager.CommonBindings(bindingCompilationService), bindingCompilationService)
.SetProperty(d => d.DataSet, dataSet.BindingOrDefault)
);
}
}
Version 2
[ControlMarkupOptions(AllowContent = false)]
public class DataPagerAsCompositeControlV2 : CompositeControl
{
public static IEnumerable<DotvvmControl> GetContents
(
//[MarkupOptions(Required = true)]
[ControlPropertyBindingDataContextChange("DataSet", order: 0), CollectionElementDataContextChange(order: 1)]
IValueBinding<IBusinessPackDataSet> dataSet
)
{
yield return new HtmlGenericControl("div")
.SetProperty("id", "testingTheThing");
var bindingCompilationService = new BindingCompilationService(
new OptionsManager<BindingCompilationOptions>(new OptionsFactory<BindingCompilationOptions>(
new List<IConfigureOptions<BindingCompilationOptions>>(),
new List<IPostConfigureOptions<BindingCompilationOptions>>())),
new DefaultExpressionToDelegateCompiler(DotvvmConfiguration.CreateDefault()),
new DefaultDotvvmCacheAdapter());
yield return new DotVVM.BusinessPack.Controls.DataPager(
new DotVVM.Framework.Controls.DataPager.CommonBindings(bindingCompilationService),
bindingCompilationService)
.SetProperty(p => p.DataSet, dataSet);
}
}
When version 1 is on the page, I get a DataPager to show up correctly. However, clicking on any of the links within it causes the following error to occur:
DotVVM.Framework.Runtime.Commands.InvalidCommandInvocationException
Nothing was found inside specified DataContext. Please check if ViewModel is populated.
Interestingly, if I add a plain BP DataPager to the page and set its DataSet property to the same object as my control and the GridView, then all the buttons work on my control.
When version 2 is on the page I get the following error as soon as the page loads, with or without the BP DataPager:
DotVVM.Framework.Compilation.DotvvmCompilationExceptionCould not compute the type of DataContext: System.Exception: Property ‘DataSet’ is required on ‘DataPagerAsCompositeControlV2’.
at DotVVM.Framework.Binding.ControlPropertyBindingDataContextChangeAttribute.GetChildDataContextType(ITypeDescriptor dataContext, IDataContextStack controlContextStack, IAbstractControl control, IPropertyDescriptor property)
at DotVVM.Framework.Compilation.ControlTree.ControlTreeResolverBase.ApplyContextChange(IDataContextStack dataContext, DataContextChangeAttribute[] attributes, IAbstractControl control, IPropertyDescriptor property)
at DotVVM.Framework.Compilation.ControlTree.ControlTreeResolverBase.GetDataContextChange(IDataContextStack dataContext, IAbstractControl control, IPropertyDescriptor property)
I do not know how to proceed. I have not been able to find any other more clear instructions on how to create a composite control and pass the properties the inner controls need to use.
Please help.
Thank you!