Skip to content

Custom event handlers in Blazor components not updating after render tree changes #11947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vaughanroberts opened this issue Jul 8, 2019 · 5 comments
Labels
area-blazor Includes: Blazor, Razor Components question
Milestone

Comments

@vaughanroberts
Copy link

I have a PropertyChangedEventHandler attached to an object in a custom component representing a table cell that works as expected until rows in the table are added or removed.
When a row is added or removed the custom events in components following that row are not attached to the correct cells.
To be clear, the normal UI events, 'onclick' etc, work correctly. However if a field in my underlying object is changed then the PropertyChanged event will be fired in a component on an incorrect table row. Depending on where I register the event it may be fired on the last row of the table or from a row above the correct row.

I have tried registering the PropertyChanged event in the component's OnInit and OnParametersSet events but they both produce incorrect behavior.

I've attached a sample project that reproduces this behavior and traces the output to the console. After inserting rows into the table, the first two rows will continue report the correct PropertChanged information, but further rows will not.

EventTest.zip

Additional context:

Blazor v3.0.0-preview6.190307.2

Cheers.

@mkArtakMSFT mkArtakMSFT added the area-blazor Includes: Blazor, Razor Components label Jul 8, 2019
@mkArtakMSFT
Copy link
Member

Thanks for contacting us, @vaughanroberts.
You need to call StateHasChanged() from the current handler, so it notifies the runtime to re-render.

@vaughanroberts
Copy link
Author

Thanks @mkArtakMSFT for the follow up, it's my first issue submission and it looks like it could of been a bit clearer. :)

I had tried StateHasChanged() in a number of places without success, but had removed them from my code sample to try and make it as simple as possible. I've attached an updated sample with comments for further explanation and clearer logging.

EventTest-2.zip

The following screenshots should help illustrate the issue.

The first screenshot shows the result of clicking on each row before inserting any new rows. This works as expected with the click event updating the counter, the PropertyChanged event being fired, and the PropertyChanged event been handled by the component.

Capture-1

After inserting a new row into position 3, clicking on the first two rows work as above, however the (new) third and (existing) fourth row's change property events aren't handled correctly. The component in row 3 doesn't handle the event at all. The component in row 4 appears to receive the event for row 3 as well as it's own.

Capture-2

Inserting (or removing) further rows continues to increase this issue.

You can see from the code sample where I have tried calling StateHasChanged(). All other aspects of the table row's components and underlying data objects update correctly, just not the PropertyChanged event handlers attached to altered row components.

I can't see where else calling StateHasChanged() would help, but would love to be corrected. :)

Cheers.

@mkArtakMSFT
Copy link
Member

Thanks for the details, @vaughanroberts.
Seems like the @key keyword is designed to solve this very issue you're facing: #8232

Having said that, we'll review this with the team one more time to see whether there is something else going on here. In the meantime, please look into the referenced feature and see whether that would help.

@mkArtakMSFT mkArtakMSFT reopened this Jul 9, 2019
@mkArtakMSFT mkArtakMSFT added this to the Discussions milestone Jul 9, 2019
@vaughanroberts
Copy link
Author

Thanks @mkArtakMSFT, this looks like exactly what I needed, apologies for overlooking it.
I've tested it with my sample code and the much more complicated scenario I'm working with, with great results.

For other reader's benefit, I also had to implement IDisposable to remove any PropertyChanged events with DataSource.PropertyChanged -= onPropertyChanged; from existing components that are reordered after the row insert.

Cheers.

@Andrzej-W
Copy link

@vaughanroberts It is a little late but you can also read this #11908. It was fixed and will be available in Preview 8.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components question
Projects
None yet
Development

No branches or pull requests

3 participants