-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
VisualElement Background/Shadow Notify
code creates a strong relationship between the brush and the element
#12344
Labels
area-drawing
Shapes, Borders, Shadows, Graphics, BoxView, custom drawing
fixed-in-8.0.0-preview.3.8149
Look for this fix in 8.0.0-preview.3.8149!
Milestone
Comments
PureWeen
changed the title
VisualElement Background
VisualElement Background/Shadow Dec 29, 2022
Notify
code creates a strong relationship between the brush and the elementNotify
code creates a strong relationship between the brush and the element
PureWeen
added
the
area-drawing
Shapes, Borders, Shadows, Graphics, BoxView, custom drawing
label
Dec 29, 2022
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
jonathanpeppers
added a commit
to jonathanpeppers/maui
that referenced
this issue
Mar 2, 2023
Fixes: dotnet#12344 Fixes: dotnet#13557 Context: https://github.com/dotnet-presentations/dotnet-maui-workshop While testing the `Monkey Finder` sample, I found the following scenario causes an issue: 1. Declare a `{StaticResource}` `Brush` at the `Application` level, with a lifetime of the entire application. 2. Set `Background` on an item in a `CollectionView`, `ListView`, etc. 3. Scroll a lot, navigate away, etc. 4. The `Brush` will hold onto any `View`'s indefinitely. The core problem here being `VisualElement` does: void NotifyBackgroundChanges() { if (Background is ImmutableBrush) return; if (Background != null) { Background.Parent = this; Background.PropertyChanged += OnBackgroundChanged; if (Background is GradientBrush gradientBrush) gradientBrush.InvalidateGradientBrushRequested += InvalidateGradientBrushRequested; } } If no user code sets `Background` to `null`, these events remain subscribed. To fix this: 1. Create a `WeakNotifyCollectionChangedProxy` type for event subscription. 2. Don't set `Background.Parent = this` ~~ General Cleanup ~~ Through doing other fixes related to memory leaks & C# events, we've started to gain a collection of `WeakEventProxy`-related types. I created some core `internal` types to be reused: * `abstract WeakEventProxy<TSource, TEventHandler>` * `WeakNotifyCollectionChangedProxy` The following classes now make use of these new shared types: * `BindingExpression` * `BindableLayout` * `ListProxy` * `VisualElement` This should hopefully reduce mistakes and reuse code in this area. ~~ Concerns ~~ Since, we are no longer doing: Background.Parent = this; This is certainly a behavior change. It is now replaced with: SetInheritedBindingContext(Background, BindingContext); I had to update one unit test that was asserting `Background.Parent`, which can assert `Background.BindingContext` instead. As such, this change is definitely sketchy and I wouldn't backport to .NET 7 immediately. We might test it out in a .NET 8 preview first.
jonathanpeppers
added a commit
to jonathanpeppers/maui
that referenced
this issue
Mar 2, 2023
Fixes: dotnet#12344 Fixes: dotnet#13557 Context: https://github.com/dotnet-presentations/dotnet-maui-workshop While testing the `Monkey Finder` sample, I found the following scenario causes an issue: 1. Declare a `{StaticResource}` `Brush` at the `Application` level, with a lifetime of the entire application. 2. Set `Background` on an item in a `CollectionView`, `ListView`, etc. 3. Scroll a lot, navigate away, etc. 4. The `Brush` will hold onto any `View`'s indefinitely. The core problem here being `VisualElement` does: void NotifyBackgroundChanges() { if (Background is ImmutableBrush) return; if (Background != null) { Background.Parent = this; Background.PropertyChanged += OnBackgroundChanged; if (Background is GradientBrush gradientBrush) gradientBrush.InvalidateGradientBrushRequested += InvalidateGradientBrushRequested; } } If no user code sets `Background` to `null`, these events remain subscribed. To fix this: 1. Create a `WeakNotifyCollectionChangedProxy` type for event subscription. 2. Don't set `Background.Parent = this` ~~ General Cleanup ~~ Through doing other fixes related to memory leaks & C# events, we've started to gain a collection of `WeakEventProxy`-related types. I created some core `internal` types to be reused: * `abstract WeakEventProxy<TSource, TEventHandler>` * `WeakNotifyCollectionChangedProxy` The following classes now make use of these new shared types: * `BindingExpression` * `BindableLayout` * `ListProxy` * `VisualElement` This should hopefully reduce mistakes and reuse code in this area. ~~ Concerns ~~ Since, we are no longer doing: Background.Parent = this; This is certainly a behavior change. It is now replaced with: SetInheritedBindingContext(Background, BindingContext); I had to update one unit test that was asserting `Background.Parent`, which can assert `Background.BindingContext` instead. As such, this change is definitely sketchy and I wouldn't backport to .NET 7 immediately. We might test it out in a .NET 8 preview first.
mattleibow
pushed a commit
that referenced
this issue
Mar 8, 2023
* [controls] fix memory leak in `VisualElement.Background` Fixes: #12344 Fixes: #13557 Context: https://github.com/dotnet-presentations/dotnet-maui-workshop While testing the `Monkey Finder` sample, I found the following scenario causes an issue: 1. Declare a `{StaticResource}` `Brush` at the `Application` level, with a lifetime of the entire application. 2. Set `Background` on an item in a `CollectionView`, `ListView`, etc. 3. Scroll a lot, navigate away, etc. 4. The `Brush` will hold onto any `View`'s indefinitely. The core problem here being `VisualElement` does: void NotifyBackgroundChanges() { if (Background is ImmutableBrush) return; if (Background != null) { Background.Parent = this; Background.PropertyChanged += OnBackgroundChanged; if (Background is GradientBrush gradientBrush) gradientBrush.InvalidateGradientBrushRequested += InvalidateGradientBrushRequested; } } If no user code sets `Background` to `null`, these events remain subscribed. To fix this: 1. Create a `WeakNotifyCollectionChangedProxy` type for event subscription. 2. Don't set `Background.Parent = this` ~~ General Cleanup ~~ Through doing other fixes related to memory leaks & C# events, we've started to gain a collection of `WeakEventProxy`-related types. I created some core `internal` types to be reused: * `abstract WeakEventProxy<TSource, TEventHandler>` * `WeakNotifyCollectionChangedProxy` The following classes now make use of these new shared types: * `BindingExpression` * `BindableLayout` * `ListProxy` * `VisualElement` This should hopefully reduce mistakes and reuse code in this area. ~~ Concerns ~~ Since, we are no longer doing: Background.Parent = this; This is certainly a behavior change. It is now replaced with: SetInheritedBindingContext(Background, BindingContext); I had to update one unit test that was asserting `Background.Parent`, which can assert `Background.BindingContext` instead. As such, this change is definitely sketchy and I wouldn't backport to .NET 7 immediately. We might test it out in a .NET 8 preview first. * Auto-format source code * Add test & subscribe to InvalidateGradientBrushRequested --------- Co-authored-by: GitHub Actions Autoformatter <autoformat@example.com>
ghost
locked as resolved and limited conversation to collaborators
Apr 7, 2023
samhouts
added
the
fixed-in-8.0.0-preview.3.8149
Look for this fix in 8.0.0-preview.3.8149!
label
Jun 8, 2023
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
area-drawing
Shapes, Borders, Shadows, Graphics, BoxView, custom drawing
fixed-in-8.0.0-preview.3.8149
Look for this fix in 8.0.0-preview.3.8149!
Description
Overall, we need to create a generalized strategy for handling
Brush
changes. There are 5 or 6 places where we use brushes but currentlyBackground
andShape
are the only ones that have some notification code.Currently this is the code we have for
Background
but it's problematic.maui/src/Controls/src/Core/VisualElement.cs
Lines 246 to 268 in cd5dd03
Parent
property probably shouldn't get set for every single type of brush. For example, right now if you have the following codeThat brush is an ImmutableBrush that will be reused everywhere that
SolidColorBrush.Green
is being used.This can cause undesirable side effects because an element that's no longer on the screen might be set as the
Parent
ofSolidColorBrush
. This can cause events to propagate up from the brush to the element that's no longer on the screen. I saw this when running the iOS device tests. Whenever I ran a test for a second time it was causing a threading exception because the previousTabbedPage
was set as parent on theImmutableBrush
which would then propagate up to the previous test run.We can easily cover
ImmutableBrush
cases.VisualElement
should subscribe to thePropertyChanged
event and ifParent
should be set on any of the Brushes. Since brushes can be reused (StaticResource) this seems like it will cause undesirable behavior. I think we need a different weaker pattern here for propagating brush changes up.The text was updated successfully, but these errors were encountered: