Is your feature request related to a problem? Please describe.
Considering this component:
public partial class Component : ComponentBase
{
[Parameter] public EventCallback<int> ValueChanged { get; set; }
}
Sometimes it's useful to store RenderFragments in fields, e.g. for templates:
@code {
private RenderFragment template = @<Component />;
}
As soon as the ValueChanged parameter is used, this breaks:
@code {
private RenderFragment template = @<Component ValueChanged="(v) => {}"/>;
}
This doesn't compile, as the usage of ValueChanged will insert this into the generated code, which isn't available in a static initializer. The crux here: I don't even want the implicit render! So while the initialization can be moved to the constructor, this isn't really an improvement, because there will now the unwanted render.
Even in regular markup for a component, there is currently no way to use this component without having an implicit render after the invocation of the callback:
<Component ValueChanged="(v) => { ThisWillBeFollowedByARender(); }" />
as it translates to (code cleaned up for clarity)
protected override void BuildRenderTree(RenderTreeBuilder __builder)
{
__builder.OpenComponent<Component>(0);
__builder.AddAttribute(1, "ValueChanged", RuntimeHelpers.TypeCheck<EventCallback<System.Int32>>(
EventCallback.Factory.Create<System.Int32>(this, (v) => { ThisWillBeFollowedByARender(); })));
__builder.CloseComponent();
}
It would be good to have a way to generate an EvenCallback<T> without the implicit re-render. This is already feasible with:
// private static readonly object no_render = new object();
builder.AddAttribute(seq, "ValueChanged", EventCallback.Factory.Create<System.Int32>(no_render, (v) => { ThisWillBeFollowedByARender(); });
So far so good for manual generation of BuildRenderTree. Sadly there's no way using razor syntax to achieve the same:
<Component ValueChanged="EventCallback.Factory.Create<int>(prevent_render, (v) => { })" />
translates to
__builder.AddAttribute(1, "ValueChanged", RuntimeHelpers.TypeCheck<EventCallback<System.Int32>>(
EventCallback.Factory.Create<System.Int32>(this,
EventCallback.Factory.Create<int>(prevent_render, (v) => { })
)));
So the razor compiler wraps the EventCallback.Factory.Create<int>(prevent_render, (v) => {}) in a EventCallback.Factory.Create<System.Int32>(this, ___). This re-introduces the this.
Describe the solution you'd like
I would like to have a way to get rid of the callback and with that also the reference to this. This could be done e.g. with
<Component ValueChanged:norender="(v) => {}"/> <!--I'm fine with other syntax too. Just a suggestion-->
translating to
__builder.AddAttribute(1, "ValueChanged", RuntimeHelpers.TypeCheck<EventCallback<System.Int32>>(
EventCallback.Factory.CreateWithoutRender<System.Int32>((v) => { })
)));
And Factory.CreateWithoutRender<T> can be implemented as (sketch):
private static readonly object no_render = new object();
EventCallback<T> CreateWithoutRender<T>(Action<T> callback) => Create<T>(no_render, callback);
I would actually already be happy with the razor compiler not wrapping my event callback with another EventCallback.Factory.Create, but I think preventing implicit rendering would be useful to many users and the implementation of this can enable the other use case too.
Is your feature request related to a problem? Please describe.
Considering this component:
Sometimes it's useful to store
RenderFragments in fields, e.g. for templates:As soon as the
ValueChangedparameter is used, this breaks:This doesn't compile, as the usage of
ValueChangedwill insertthisinto the generated code, which isn't available in a static initializer. The crux here: I don't even want the implicit render! So while the initialization can be moved to the constructor, this isn't really an improvement, because there will now the unwanted render.Even in regular markup for a component, there is currently no way to use this component without having an implicit render after the invocation of the callback:
as it translates to (code cleaned up for clarity)
It would be good to have a way to generate an
EvenCallback<T>without the implicit re-render. This is already feasible with:So far so good for manual generation of
BuildRenderTree. Sadly there's no way using razor syntax to achieve the same:translates to
So the razor compiler wraps the
EventCallback.Factory.Create<int>(prevent_render, (v) => {})in aEventCallback.Factory.Create<System.Int32>(this, ___). This re-introduces thethis.Describe the solution you'd like
I would like to have a way to get rid of the callback and with that also the reference to this. This could be done e.g. with
translating to
And
Factory.CreateWithoutRender<T>can be implemented as (sketch):I would actually already be happy with the razor compiler not wrapping my event callback with another
EventCallback.Factory.Create, but I think preventing implicit rendering would be useful to many users and the implementation of this can enable the other use case too.