Browse Source

Preserve container themes set locally.

pull/12630/head
Steven Kirk 3 years ago
parent
commit
03ff228a6d
  1. 28
      src/Avalonia.Controls/ItemsControl.cs
  2. 39
      tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

28
src/Avalonia.Controls/ItemsControl.cs

@ -67,6 +67,9 @@ namespace Avalonia.Controls
public static readonly StyledProperty<IBinding?> DisplayMemberBindingProperty =
AvaloniaProperty.Register<ItemsControl, IBinding?>(nameof(DisplayMemberBinding));
private static readonly AttachedProperty<ControlTheme?> AppliedItemContainerTheme =
AvaloniaProperty.RegisterAttached<ItemsControl, Control, ControlTheme?>("HasAppliedItemContainerTheme");
/// <summary>
/// Gets or sets the <see cref="IBinding"/> to use for binding to the display member of each item.
/// </summary>
@ -663,12 +666,27 @@ namespace Avalonia.Controls
internal void PrepareItemContainer(Control container, object? item, int index)
{
var itemContainerTheme = ItemContainerTheme;
// If the container has no theme set, or we've already applied our ItemContainerTheme
// (and it hasn't changed since) then we're in control of the container's Theme and may
// need to update it.
if (!container.IsSet(ThemeProperty) || container.GetValue(AppliedItemContainerTheme) == container.Theme)
{
var itemContainerTheme = ItemContainerTheme;
if (itemContainerTheme is null)
container.Theme = null;
else if (itemContainerTheme.TargetType?.IsAssignableFrom(GetStyleKey(container)) == true)
container.Theme = itemContainerTheme;
if (itemContainerTheme?.TargetType?.IsAssignableFrom(GetStyleKey(container)) == true)
{
// We have an ItemContainerTheme and it matches the container. Set the Theme
// property, and mark the container as having had ItemContainerTheme applied.
container.SetCurrentValue(ThemeProperty, itemContainerTheme);
container.SetValue(AppliedItemContainerTheme, itemContainerTheme);
}
else
{
// Otherwise clear the theme and the HasAppliedItemContainerTheme property.
container.ClearValue(ThemeProperty);
container.ClearValue(AppliedItemContainerTheme);
}
}
if (item is not Control)
container.DataContext = item;

39
tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs

@ -239,6 +239,45 @@ namespace Avalonia.Controls.UnitTests
Assert.Null(container.Background);
}
[Fact]
public void ItemContainerTheme_Should_Not_Override_LocalValue_Theme()
{
using var app = Start();
var theme1 = new ControlTheme
{
TargetType = typeof(ContentPresenter),
Setters = { new Setter(ContentPresenter.BackgroundProperty, Brushes.Red) }
};
var theme2 = new ControlTheme
{
TargetType = typeof(Control),
Setters = { new Setter(ContentPresenter.BackgroundProperty, Brushes.Green) }
};
var items = new object[]
{
new ContentPresenter(),
new ContentPresenter
{
Theme = theme2
},
};
var target = CreateTarget(
itemsSource: items,
itemContainerTheme: theme1);
Assert.Same(theme1, GetContainer(target, 0).Theme);
Assert.Same(theme2, GetContainer(target, 1).Theme);
target.ItemContainerTheme = null;
Assert.Null(GetContainer(target, 0).Theme);
Assert.Same(theme2, GetContainer(target, 1).Theme);
}
[Fact]
public void Container_Should_Have_LogicalParent_Set_To_ItemsControl()
{

Loading…
Cancel
Save