These are chat archives for AvaloniaUI/Avalonia

26th
May 2016
danwalmsley
@danwalmsley
May 26 2016 00:06
pr coming up..
it wont be ready to merge
but I will chat with you tomorrow about it
danwalmsley
@danwalmsley
May 26 2016 09:13
@wieslawsoltes @grokys when using behaviours, I'm seeing that DetectedFromLogicalTree and OnDetaching are never being called?
 <i:Interaction.Behaviors>
            <behaviours:CodeInformationToolTipBehavior>
              <cont:HoverProbe DataContext="{Binding HoverProbe}" />
            </behaviours:CodeInformationToolTipBehavior>
it ends up holding a reference and preventing clean up of memory
is that a bug? the behaviour should get detached when the view closed?
ah ok forget that
I overrode OnDetaching in the derived and didn't call base.onDetaching!
no wait
OnDetaching definitely doesn't call my original statement stands
I can call this though ...
AssociatedObject.DetachedFromLogicalTree += (sender, e) =>
as a workaround, perhaps behaviors should do this internally?
danwalmsley
@danwalmsley
May 26 2016 09:52
@grokys I think I found the memory leak in ContentPresenter...
its not passing on its detach events to the controls that end up inside the content presenter
so stuff doesn't get cleaned up
this is a list box inside the content presenter, which has now been closed...
image.png
everything above the content presenter is clean up
but the inheritanceParent is still set inside my listbox which is inside the content presenter!
If I get rid of the listbox inside the content presenter stuff starts cleaning up again.
does that look like its the problem there?
Wiesław Šoltés
@wieslawsoltes
May 26 2016 10:11

OnDetaching definitely doesn't call my original statement stands

@danwalmsley I tested this with BehaviorsTestApplication and switched between CustomBehavior tab and OnDetaching was called, so maybe this issue is specific to your Xaml and Avalonia ?

danwalmsley
@danwalmsley
May 26 2016 10:26
@wieslawsoltes ok then it might be that my behaviour has a popup in it
which also contains content control
I'm finding popup and content control are 2 major source of memory leaks
and then they might be preventing the OnDetatching getting called
Wiesław Šoltés
@wieslawsoltes
May 26 2016 10:29
@danwalmsley I agree with you, especially for my cases the ContentControl is major source of leaks.
Wiesław Šoltés
@wieslawsoltes
May 26 2016 10:35
@danwalmsley I have also checked this behavior https://github.com/XamlBehaviors/XamlBehaviors/blob/master/samples/BehaviorsTestApplicationPcl/Views/MainWindow.xaml#L139
and OnDetaching is called when switching between tabs.
Ivan Kochurkin
@KvanTTT
May 26 2016 10:37
Hi! Is it possible to set icon for Avalonia application?
Steven Kirk
@grokys
May 26 2016 10:58
@KvanTTT that's not implemented yet but it shouldn't be hard to do
@wieslawsoltes @danwalmsley has anyone been able to pin down the ContentControl leak?
danwalmsley
@danwalmsley
May 26 2016 11:11
@grokys I haven't pinned it down for sure
but from running dot memory on it
it looks to me that stuff inside the content presenter isn't getting cleaned up or detached when the content presenter is removed from visual / logical tree?
that's a naïve idea about what is happening
Ivan Kochurkin
@KvanTTT
May 26 2016 11:27
Ok. I created new issue: AvaloniaUI/Avalonia#548
Steven Kirk
@grokys
May 26 2016 11:28
thanks. one thing to consider is that i don't think .ico files are x-plat
danwalmsley
@danwalmsley
May 26 2016 11:50
@KvanTTT I created my own custom window class "MetroWindow"
and implemented my own icon using resourse or a path
danwalmsley
@danwalmsley
May 26 2016 21:08
@grokys I'm looking into the problem with popup holding references to stuff, I reckon its related to contentcontrol, since the popup contains one...
danwalmsley
@danwalmsley
May 26 2016 21:16
my suspicion is it needs ondetachedfrom logical handling
i.e.
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
        {
            base.OnDetachedFromLogicalTree(e);
            Child = null;
            _createdChild = false;
        }
otherwise it holds a ref to child?
Steven Kirk
@grokys
May 26 2016 21:25
Sorry not at my computer this evening
The way to find out is to write a leak test that fails and then try your fix
Anything else is just guessing
danwalmsley
@danwalmsley
May 26 2016 21:26
yeh
ok cheers, i'll try and copy an existing leak test
Steven Kirk
@grokys
May 26 2016 21:55
ok i'm at a computer for a bit now so let me know if you have qs
danwalmsley
@danwalmsley
May 26 2016 21:57
ok iv made some tests, but they don't fail
is it possible to apply styles and do some binding in the leak tests?
this is what I have so far
[Fact]
        public void Popup_is_Free()
        {
            using (UnitTestApplication.Start(TestServices.StyledWindow))
            {
                Func<Window> run = () =>
                {
                    var nodes = new[]
                    {
                        new Node
                        {
                            Children = new[] { new Node() },
                        }
                    };

                    Popup target;

                    var window = new Window
                    {
                        Content = target = new Popup()
                        {
                            Child = new TreeView()
                            {
                                DataTemplates = new DataTemplates
                            {
                                new FuncTreeDataTemplate<Node>(
                                    x => new TextBlock { Text = x.Name },
                                    x => x.Children)
                            },
                                Items = nodes
                            }
                        }
                    };

                    // Do a layout and make sure that TreeViewItems get realized.
                    LayoutManager.Instance.ExecuteInitialLayoutPass(window);
                    //Assert.Equal(1, target.ItemContainerGenerator.Containers.Count());

                    target.Open();
                    target.Close();
                    // Clear the content and ensure the TreeView is removed.
                    window.Content = null;
                    LayoutManager.Instance.ExecuteLayoutPass();
                    Assert.Null(window.Presenter.Child);

                    return window;
                };

                var result = run();

                dotMemory.Check(memory =>
                    Assert.Equal(0, memory.GetObjects(where => where.Type.Is<ContentControl>()).ObjectsCount));
            }
        }
also this popup test threw an exception at first
private double GetLayoutScale()
        {
            var result =  (VisualRoot as ILayoutRoot)?.LayoutScaling ?? 1.0;
            result = 1.0;
            if (result == 0 || double.IsNaN(result) || double.IsInfinity(result))
            {
                throw new Exception($"Invalid LayoutScaling returned from {VisualRoot.GetType()}");
            }

            return result;
        }
I had to add the result = 1.0 to make it work
in Layoutable.cs
how can I satisfy LayoutScaling inside the test?
Steven Kirk
@grokys
May 26 2016 22:08
ah that'll be because IPopupImpl isn't being mocked because it wasn't needed
first, get a failing test then worry about mocking that i'd say
TextBox_With_Xaml_Binding_Is_Freed does binding
to test styles just set some styles on your window in code
danwalmsley
@danwalmsley
May 26 2016 22:10
do you need to do something to get them to applied, so they endup in style_applied disctionary?
or does a layout pass handle all that?
Steven Kirk
@grokys
May 26 2016 22:12
they should be applied to each control as it's added to a rooted logical tree
here's an example of a unit test with styles: