Trying to pass an EventHandler to a Blazor component. Error I'm getting: The event AppState.IntegerChanged can only appear on the left hand side of +=
Seems like this should work, is it a blazor limitation or am I doing something wrong?
Getting compiler error in MixedNumber.razor trying to assign event to ValueChanged.
Thanks
MixedNumber.razor
@inject AppState AppState
<CustomInput ValueChanged=@AppState.IntegerChanged> </CustomInput>
<CustomInput ValueChanged=@AppState.NumeratorChanged> </CustomInput>
<CustomInput ValueChanged=@AppState.DenominatorChanged> </CustomInput>
@code {
[Parameter] public EventHandler<CustomValidationResult> ValueChanged { get; set; }
public void MixedValueChanged()
{
CustomValidationResult result = new() { Integer = 1, Numerator = 10, Denominator = 100 };
AppState.OnMixedChanged(result);
}
public class CustomValidationResult
{
public double Integer { get; set; }
public double Numerator { get; set; }
public double Denominator { get; set; }
}
}
CustomInput.razor
@code {
[Parameter] public EventHandler<double>? ValueChanged { get; set; }
protected override void OnInitialized()
{
base.OnInitialized();
ValueChanged += valueChanged;
}
public void valueChanged(object sender, double newValue)
{
//do something
}
}
AppState.cs
public class AppState
{
public static event EventHandler<double>? IntegerChanged;
public static event EventHandler<double>? NumeratorChanged;
public static event EventHandler<double>? DenominatorChanged;
public static void OnMixedChanged(MixedNumber.CustomValidationResult result)
{
IntegerChanged?.Invoke(new object(), result.Integer);
NumeratorChanged?.Invoke(new object(), result.Numerator);
DenominatorChanged?.Invoke(new object(), result.Denominator);
}
}
is it a blazor limitation
No.
or am I doing something wrong?
Yes.
public static event EventHandler<double>? IntegerChanged;
An event
is a special kind of property, only stricter. It does not even allow read-access, only (un)subscribing with +=
and -=
. It protects abuse of the underlying delegate that is a value type.
You code as-is will compile when you simply remove the event
keyword. But it won't work because you subscribe to a copy of the delegate. And when you think that is confusing: that is why the event
mechanism was invented.
And there is a strong Blazor guideline against setting a [Parameter]
from the inside.
Now for a solution: I don't see a need for an event
here. It's much simpler.
Give CustomInput a Value property and you're done. You can use OnParameterSet() to react to a value change. And since it is an Input, you probably want to include a Callback.
@code {
[Parameter]
public double Value { get; set; } // don't use the set in this file
[Parameter]
public EventCallback<double> ValueChanged { get; set; } // same
... ValueChanged.InvokeAsync(localValue);
}
@inject AppState AppState
<CustomInput @bind-Value=@AppState.Integer> </CustomInput>
// or:
<CustomInput Value=@AppState.Numerator ValueChanged=AppState.NumeratorChanged > </CustomInput>