user1068557
user1068557

Reputation: 379

How to pass EventHandler as parameter in Blazor

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 [email protected]> </CustomInput>
<CustomInput [email protected]> </CustomInput>
<CustomInput [email protected]> </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);
    }

}

Upvotes: 4

Views: 2049

Answers (2)

Henk Holterman
Henk Holterman

Reputation: 273844

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 @[email protected]> </CustomInput>

// or:

<CustomInput [email protected] ValueChanged=AppState.NumeratorChanged > </CustomInput>

Upvotes: 4

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30465

[Parameter] public EventHandler<double>? ValueChanged { get; set; }

defines a delegate pattern Task MethodName(double value). Any method that fits this pattern can be assigned to Parameter in the component declaration.

However you are trying to assign an event to it. You are trying to plug two male sockets together. Both are generators of events, not receivers.

As your intent is not clear from the code snippets provided, all I can say is - Time to rethink.

Upvotes: -1

Related Questions