Browse Source
Fixed TabItem.ContentTemplate being reused for the next tab item (#17141)
pull/17145/head
Tom Edwards
2 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with
48 additions and
2 deletions
-
src/Avalonia.Controls/TabControl.cs
-
tests/Avalonia.Controls.UnitTests/TabControlTests.cs
|
|
|
@ -207,10 +207,21 @@ namespace Avalonia.Controls |
|
|
|
container ??= ContainerFromIndex(SelectedIndex); |
|
|
|
if (container != null) |
|
|
|
{ |
|
|
|
if (SelectedContentTemplate != SelectContentTemplate(container.GetValue(ContentTemplateProperty))) |
|
|
|
{ |
|
|
|
// If the value of SelectedContentTemplate is about to change, clear it first. This ensures
|
|
|
|
// that the template is not reused as soon as SelectedContent changes in the statement below
|
|
|
|
// this block, and also that controls generated from it are unloaded before SelectedContent
|
|
|
|
// (which is typically their DataContext) changes.
|
|
|
|
SelectedContentTemplate = null; |
|
|
|
} |
|
|
|
|
|
|
|
_selectedItemSubscriptions = new CompositeDisposable( |
|
|
|
container.GetObservable(ContentControl.ContentProperty).Subscribe(v => SelectedContent = v), |
|
|
|
// Note how we fall back to our own ContentTemplate if the container doesn't specify one
|
|
|
|
container.GetObservable(ContentControl.ContentTemplateProperty).Subscribe(v => SelectedContentTemplate = v ?? ContentTemplate)); |
|
|
|
container.GetObservable(ContentControl.ContentTemplateProperty).Subscribe(v => SelectedContentTemplate = SelectContentTemplate(v))); |
|
|
|
|
|
|
|
// Note how we fall back to our own ContentTemplate if the container doesn't specify one
|
|
|
|
IDataTemplate? SelectContentTemplate(IDataTemplate? containerTemplate) => containerTemplate ?? ContentTemplate; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -405,6 +405,41 @@ namespace Avalonia.Controls.UnitTests |
|
|
|
Assert.Equal("bar", Assert.IsType<TextBlock>(target.ContentPart.Child).Tag); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Previous_ContentTemplate_Is_Not_Reused_When_TabItem_Changes() |
|
|
|
{ |
|
|
|
int templatesBuilt = 0; |
|
|
|
|
|
|
|
var target = new TabControl |
|
|
|
{ |
|
|
|
Template = TabControlTemplate(), |
|
|
|
Items = |
|
|
|
{ |
|
|
|
TabItemFactory("First tab content"), |
|
|
|
TabItemFactory("Second tab content"), |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
var root = new TestRoot(target); |
|
|
|
ApplyTemplate(target); |
|
|
|
|
|
|
|
target.SelectedIndex = 0; |
|
|
|
target.SelectedIndex = 1; |
|
|
|
|
|
|
|
Assert.Equal(2, templatesBuilt); |
|
|
|
|
|
|
|
TabItem TabItemFactory(object content) => new() |
|
|
|
{ |
|
|
|
Content = content, |
|
|
|
ContentTemplate = new FuncDataTemplate<object>((actual, ns) => |
|
|
|
{ |
|
|
|
Assert.Equal(content, actual); |
|
|
|
templatesBuilt++; |
|
|
|
return new Border(); |
|
|
|
}) |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Should_Not_Propagate_DataContext_To_TabItem_Content() |
|
|
|
{ |
|
|
|
|