I'm having some issues in defining styles of my items. Or actually in the scope of the styles I set. My question is how do I make sure, that a style I'm setting is not propagated for the elements of the same type, that are enclosed in the top-level type?
Let me give you a short example of my issue.
Assume we have a following class, containing a name of some person and a list of cars they own:
public class Person
{
public string Name { get; set; } = string.Empty;
public ObservableCollection<string> Cars { get; set; } = [];
}
In my view model I create an observable collection, filled in in place (for the purpose of this example):
public ObservableCollection<Person> People { get; set; } =
[
new Person() { Name = "Kristoforo Truitt", Cars = [ "Lexus", "GMC", "Dodge", "Hyundai", ] },
new Person() { Name = "Phil Gladwell", Cars = [ "Lexus", "Chevrolet", "Lexus", "Subaru", ] },
new Person() { Name = "Giacobo Commusso", Cars = [ "Isuzu", "Suzuki", "Mitsubishi", "Subaru", ] },
new Person() { Name = "Christina Ramsbottom", Cars = [ "Ford", "GMC", "Volkswagen", "Chevrolet", ] },
new Person() { Name = "Karl Cochern", Cars = [ "Mercury", "Toyota", "Ford", "Mitsubishi", ] },
];
Now, in my AXAML I'm putting the following ListBox
displaying all persons and all their cars next to their name:
<ListBox ItemsSource="{Binding People}" Background="Transparent" Classes="PeopleList">
<ListBox.Styles>
<Style Selector="ListBox.PeopleList ListBoxItem:nth-child(2n)">
<Setter Property="Background" Value="#EFEFEF" />
</Style>
</ListBox.Styles>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<ListBox ItemsSource="{Binding Cars}" Background="Transparent" Margin="10,0" Classes="CarsList">
<ListBox.Styles>
<Style Selector="ListBox.CarsList ListBoxItem">
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
</Style>
</ListBox.Styles>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
To give some separation between the items (person) I'm defining a style, where every second item has a background defined: <Style Selector="ListBox.PeopleList ListBoxItem:nth-child(2n)">...
. Even though I've tried to have this style applied to the "outer" ListBox (classes, etc.), this it what I'm getting:
As you can see, also the cars listed have their background set (every second one).
What I would like to achieve is this:
So my question is - how do I limit the scope of the style of the outer ListBox only to itself, and the inner ListBox does not inherit it?
Here is the explanation why ListBox.PeopleList > ListBoxItem:nth-child(2n)
works!
According to the avalonia ui documentation style selector syntax:
>
is Child Operator, in your case, ListBoxItem
is the direct children of ListBox
in the logical tree, ListBox.PeopleList > ListBoxItem:nth-child(2n)
means "only ListBoxItem that is the direct children of ListBox with PeopleList class" is selected, so only outer one matches.
A child selector is defined by separating two selectors with a > character. This selector matches only direct children in the logical controls tree.
On the other hand, a space is Any Descendant Operator, both outer and inner ListBoxItem
in your case match.
When two selectors are separated by a space, then the selector will match any descendants in the logical tree. The parent is on the left, and the descendant is on the right.