From 10002deee43bb4205e77cedfad94e67238974f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Standa=20Luke=C5=A1?= Date: Sun, 24 Nov 2024 22:46:14 +0100 Subject: [PATCH] Fix some issues with incorrect binding result types * ExpectedType property can now be null, when the assigned property is unknwon: - this means that CreateBinding will actually create a strongly typed instance, instead of just ValueBindingExpression or similar * AutoUI uses props.Property instead of CreateValueBinding where possible --- .../EnumComboBoxFormEditorProvider.cs | 2 +- .../GridColumns/CheckBoxGridColumnProvider.cs | 2 +- .../Binding/GeneralBindingPropertyResolvers.cs | 18 +++++++++++++----- .../Controls/GridViewCheckBoxColumn.cs | 4 ++-- .../Controls/GridViewDataSetBindingProvider.cs | 4 ++-- src/Framework/Framework/Controls/Literal.cs | 2 +- .../Abstractions/SamplesRouteUrls.designer.cs | 2 +- .../Tests/Tests/Control/GridViewTests.cs | 4 ++-- .../DataPagerTests.CommandDataPager.html | 4 ++-- .../DataPagerTests.StaticCommandPager.html | 4 ++-- 10 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/AutoUI/Core/PropertyHandlers/FormEditors/EnumComboBoxFormEditorProvider.cs b/src/AutoUI/Core/PropertyHandlers/FormEditors/EnumComboBoxFormEditorProvider.cs index c8d86ff239..3516459bd8 100644 --- a/src/AutoUI/Core/PropertyHandlers/FormEditors/EnumComboBoxFormEditorProvider.cs +++ b/src/AutoUI/Core/PropertyHandlers/FormEditors/EnumComboBoxFormEditorProvider.cs @@ -42,7 +42,7 @@ public override DotvvmControl CreateControl(PropertyDisplayMetadata property, Au .SetCapability(props.Html) .SetProperty(c => c.Enabled, props.Enabled) .SetProperty(c => c.SelectionChanged, props.Changed) - .SetProperty(c => c.SelectedValue, (IValueBinding)context.CreateValueBinding(property)); + .SetProperty(c => c.SelectedValue, props.Property); if (isNullable) { diff --git a/src/AutoUI/Core/PropertyHandlers/GridColumns/CheckBoxGridColumnProvider.cs b/src/AutoUI/Core/PropertyHandlers/GridColumns/CheckBoxGridColumnProvider.cs index e8b0772665..1d2b46e7a5 100644 --- a/src/AutoUI/Core/PropertyHandlers/GridColumns/CheckBoxGridColumnProvider.cs +++ b/src/AutoUI/Core/PropertyHandlers/GridColumns/CheckBoxGridColumnProvider.cs @@ -15,7 +15,7 @@ public override bool CanHandleProperty(PropertyDisplayMetadata property, AutoUIC protected override GridViewColumn CreateColumnCore(PropertyDisplayMetadata property, AutoGridViewColumn.Props props, AutoUIContext context) { var column = new GridViewCheckBoxColumn(); - column.SetBinding(GridViewCheckBoxColumn.ValueBindingProperty, context.CreateValueBinding(property)); + column.SetBinding(GridViewCheckBoxColumn.ValueBindingProperty, props.Property); return column; } } diff --git a/src/Framework/Framework/Compilation/Binding/GeneralBindingPropertyResolvers.cs b/src/Framework/Framework/Compilation/Binding/GeneralBindingPropertyResolvers.cs index 75c7da5ea8..694801823f 100644 --- a/src/Framework/Framework/Compilation/Binding/GeneralBindingPropertyResolvers.cs +++ b/src/Framework/Framework/Compilation/Binding/GeneralBindingPropertyResolvers.cs @@ -174,12 +174,20 @@ expression is JsNewExpression || public ResultTypeBindingProperty GetResultType(ParsedExpressionBindingProperty expression) => new ResultTypeBindingProperty(expression.Expression.Type); - public ExpectedTypeBindingProperty GetExpectedType(AssignedPropertyBindingProperty? property = null) + public ExpectedTypeBindingProperty? GetExpectedType(AssignedPropertyBindingProperty? property = null) { var prop = property?.DotvvmProperty; - if (prop == null) return new ExpectedTypeBindingProperty(typeof(object)); + if (prop == null) return null; - return new ExpectedTypeBindingProperty(prop.IsBindingProperty ? (prop.PropertyType.GenericTypeArguments.SingleOrDefault() ?? typeof(object)) : prop.PropertyType); + if (prop.IsBindingProperty) + { + if (prop.PropertyType.GenericTypeArguments.SingleOrDefault() is {} type) + return new ExpectedTypeBindingProperty(type); + else + return null; + } + + return new ExpectedTypeBindingProperty(prop.PropertyType); } public BindingCompilationRequirementsAttribute GetAdditionalResolversFromProperty(AssignedPropertyBindingProperty property) @@ -264,9 +272,9 @@ public NegatedBindingExpression NegateBinding(ParsedExpressionBindingProperty e, (Expression)Expression.Not(e.Expression) )); } - public ExpectedAsStringBindingExpression ExpectAsStringBinding(ParsedExpressionBindingProperty e, ExpectedTypeBindingProperty expectedType, IBinding binding) + public ExpectedAsStringBindingExpression ExpectAsStringBinding(ParsedExpressionBindingProperty e, IBinding binding, ExpectedTypeBindingProperty? expectedType = null) { - if (expectedType.Type == typeof(string)) + if (expectedType is {} && expectedType.Type == typeof(string)) return new(binding); return new(binding.DeriveBinding(new ExpectedTypeBindingProperty(typeof(string)), e)); diff --git a/src/Framework/Framework/Controls/GridViewCheckBoxColumn.cs b/src/Framework/Framework/Controls/GridViewCheckBoxColumn.cs index 81ba6dde4a..e42a47b638 100644 --- a/src/Framework/Framework/Controls/GridViewCheckBoxColumn.cs +++ b/src/Framework/Framework/Controls/GridViewCheckBoxColumn.cs @@ -15,9 +15,9 @@ public class GridViewCheckBoxColumn : GridViewColumn /// Gets or sets a binding which retrieves the value to display from the current data item. /// [MarkupOptions(AllowHardCodedValue = false, Required = true)] - public IStaticValueBinding ValueBinding + public IStaticValueBinding ValueBinding { - get { return (IStaticValueBinding)GetValueRaw(ValueBindingProperty)!; } + get { return (IStaticValueBinding)GetValueRaw(ValueBindingProperty)!; } set { SetValue(ValueBindingProperty, value); } } public static readonly DotvvmProperty ValueBindingProperty = diff --git a/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs b/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs index 9c38e9b06f..36e994668f 100644 --- a/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs +++ b/src/Framework/Framework/Controls/GridViewDataSetBindingProvider.cs @@ -119,8 +119,8 @@ ParameterExpression CreateParameter(DataContextStack dataContextStack, string na : null, PageNumberText = isServerOnly switch { - true => service.Cache.CreateResourceBinding("_this + 1", pageIndexDataContext), - false => service.Cache.CreateValueBinding("_this + 1", pageIndexDataContext) + true => service.Cache.CreateResourceBinding("(_this + 1) + ''", pageIndexDataContext), + false => service.Cache.CreateValueBinding("(_this + 1) + ''", pageIndexDataContext) }, HasMoreThanOnePage = GetValueBindingOrNull, bool>(d => d.PagingOptions.PagesCount > 1) ?? diff --git a/src/Framework/Framework/Controls/Literal.cs b/src/Framework/Framework/Controls/Literal.cs index 813ed32d6a..c2d69ea937 100644 --- a/src/Framework/Framework/Controls/Literal.cs +++ b/src/Framework/Framework/Controls/Literal.cs @@ -97,7 +97,7 @@ bool isFormattedType(Type? type) => type != null && (type == typeof(float) || type == typeof(double) || type == typeof(decimal) || type == typeof(DateTime) || type == typeof(DateOnly) || type == typeof(TimeOnly) || isFormattedType(Nullable.GetUnderlyingType(type))); - bool isFormattedTypeOrObj(Type? type) => type == typeof(object) || isFormattedType(type); + bool isFormattedTypeOrObj(Type? type) => type is null || type == typeof(object) || isFormattedType(type); return isFormattedType(binding?.ResultType) && isFormattedTypeOrObj(binding?.GetProperty(ErrorHandlingMode.ReturnNull)?.Type); } diff --git a/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs b/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs index 8d4e6bf335..bd65692afc 100644 --- a/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs +++ b/src/Samples/Tests/Abstractions/SamplesRouteUrls.designer.cs @@ -87,7 +87,7 @@ public partial class SamplesRouteUrls public const string ControlSamples_GridView_GridViewInlineEditingPrimaryKeyString = "ControlSamples/GridView/GridViewInlineEditingPrimaryKeyString"; public const string ControlSamples_GridView_GridViewInlineEditingValidation = "ControlSamples/GridView/GridViewInlineEditingValidation"; public const string ControlSamples_GridView_GridViewPagingSorting = "ControlSamples/GridView/GridViewPagingSorting"; - public const string ControlSamples_GridView_GridViewPagingSortingServerOnly = "ControlSamples/GridView/GridViewPagingSortingServerOnly"; + public const string ControlSamples_GridView_GridViewPagingSortingServerSide = "ControlSamples/GridView/GridViewPagingSortingServerSide"; public const string ControlSamples_GridView_GridViewRowDecorators = "ControlSamples/GridView/GridViewRowDecorators"; public const string ControlSamples_GridView_GridViewServerRender = "ControlSamples/GridView/GridViewServerRender"; public const string ControlSamples_GridView_GridViewSortChanged = "ControlSamples/GridView/GridViewSortChanged"; diff --git a/src/Samples/Tests/Tests/Control/GridViewTests.cs b/src/Samples/Tests/Tests/Control/GridViewTests.cs index f3838c83ae..3faf455677 100644 --- a/src/Samples/Tests/Tests/Control/GridViewTests.cs +++ b/src/Samples/Tests/Tests/Control/GridViewTests.cs @@ -510,10 +510,10 @@ public void Control_GridView_GridViewInlineEditing_PagingWhenEditing(string path [Theory] [InlineData(SamplesRouteUrls.ControlSamples_GridView_GridViewPagingSorting)] [InlineData(SamplesRouteUrls.ControlSamples_GridView_GridViewServerRender)] - [InlineData(SamplesRouteUrls.ControlSamples_GridView_GridViewPagingSortingServerOnly)] + [InlineData(SamplesRouteUrls.ControlSamples_GridView_GridViewPagingSortingServerSide)] [SampleReference(nameof(SamplesRouteUrls.ControlSamples_GridView_GridViewPagingSorting))] [SampleReference(nameof(SamplesRouteUrls.ControlSamples_GridView_GridViewServerRender))] - [SampleReference(nameof(SamplesRouteUrls.ControlSamples_GridView_GridViewPagingSortingServerOnly))] + [SampleReference(nameof(SamplesRouteUrls.ControlSamples_GridView_GridViewPagingSortingServerSide))] public void Control_GridView_GridViewPagingSortingBase(string path) { RunInAllBrowsers(browser => { diff --git a/src/Tests/ControlTests/testoutputs/DataPagerTests.CommandDataPager.html b/src/Tests/ControlTests/testoutputs/DataPagerTests.CommandDataPager.html index 98b22e1a00..a061797212 100644 --- a/src/Tests/ControlTests/testoutputs/DataPagerTests.CommandDataPager.html +++ b/src/Tests/ControlTests/testoutputs/DataPagerTests.CommandDataPager.html @@ -11,10 +11,10 @@
  • - + - +
  • diff --git a/src/Tests/ControlTests/testoutputs/DataPagerTests.StaticCommandPager.html b/src/Tests/ControlTests/testoutputs/DataPagerTests.StaticCommandPager.html index c40e8e9169..932afdb9f0 100644 --- a/src/Tests/ControlTests/testoutputs/DataPagerTests.StaticCommandPager.html +++ b/src/Tests/ControlTests/testoutputs/DataPagerTests.StaticCommandPager.html @@ -17,13 +17,13 @@
  • - - +