Repository: AvaloniaUI/Avalonia

Issue:
Styles are mistakenly activated when multiple selectors (with and without activators) are combined on the same Style instance
### Discussed in https://github.com/AvaloniaUI/Avalonia/discussions/13908

Having complex and mixed selector like `Button.SingleLineButton, ToggleButton.SingleLineButton, ComboBox.SingleLineCombobox, MenuItem` at some point of styles evaluation Style will be attached to the MenuItem without any activator (as it always matches). Unfortunately, it will break `Style._sharedInstance`, as current Style system will share instance for all parts of the selector, not only MenuItem. 
CC @grokys I might take a look this week if I can fix it. But if you have a clear idea how to fix it now - please do.

<div type='discussions-op-text'>

<sup>Originally posted by **giacarrea** December 11, 2023</sup>
Hello, I'm busy trying to port an existing app from avalonia 10 to 11 and I'm having the following issue:

I have a class specific styling for button  mixed in with other controls, but when switching to avalonia 11,  some buttons that weren't assigned to that class in my axaml file were somehow assigned to it regardless - as I could notice in the ui dev tool.

Weirder still, when I split my styling over two différent styles, it then worked as intended... (see screenshot)
![image](https://github.com/AvaloniaUI/Avalonia/assets/60611503/6eeafddb-2a30-44f6-adba-3b2ef000e3a7)

Also, the same window presenting the issue will be displayed correctly the first time its rendered. If I close it, open another one, then reopen the first one, then I get my styling issue...

Similarly, I have a button with a flyout menu; if I remove the menuItem, I don't have the styling issue anymore (which happens on another window...)

![image](https://github.com/AvaloniaUI/Avalonia/assets/60611503/93c6e4e3-08fc-44b1-979a-c5eb6005ba70)

Has anyone ever had a similar issue or know where it could come from?</div>


Hints:
Workaround: create separated styles with and without activators (with and without classes/pseudoclasses/properties selectors).

Patch:
diff --git a/src/Avalonia.Base/Styling/ControlTheme.cs b/src/Avalonia.Base/Styling/ControlTheme.cs
index 75a3beb9078..6cd09e18081 100644
--- a/src/Avalonia.Base/Styling/ControlTheme.cs
+++ b/src/Avalonia.Base/Styling/ControlTheme.cs
@@ -48,7 +48,7 @@ internal SelectorMatchResult TryAttach(StyledElement target, FrameType type)
 
             if (HasSettersOrAnimations && TargetType.IsAssignableFrom(StyledElement.GetStyleKey(target)))
             {
-                Attach(target, null, type);
+                Attach(target, null, type, true);
                 return SelectorMatchResult.AlwaysThisType;
             }
 
diff --git a/src/Avalonia.Base/Styling/Style.cs b/src/Avalonia.Base/Styling/Style.cs
index a5d89392e97..44ffc22e915 100644
--- a/src/Avalonia.Base/Styling/Style.cs
+++ b/src/Avalonia.Base/Styling/Style.cs
@@ -74,7 +74,7 @@ internal SelectorMatchResult TryAttach(StyledElement target, object? host, Frame
 
                 if (match.IsMatch)
                 {
-                    Attach(target, match.Activator, type);
+                    Attach(target, match.Activator, type, Selector is not OrSelector);
                 }
 
                 result = match.Result;
diff --git a/src/Avalonia.Base/Styling/StyleBase.cs b/src/Avalonia.Base/Styling/StyleBase.cs
index 318e8d68901..bc3457cb481 100644
--- a/src/Avalonia.Base/Styling/StyleBase.cs
+++ b/src/Avalonia.Base/Styling/StyleBase.cs
@@ -92,20 +92,24 @@ public bool TryGetResource(object key, ThemeVariant? themeVariant, out object? r
             return false;
         }
 
-        internal ValueFrame Attach(StyledElement target, IStyleActivator? activator, FrameType type)
+        internal ValueFrame Attach(
+            StyledElement target,
+            IStyleActivator? activator,
+            FrameType type,
+            bool canShareInstance)
         {
             if (target is not AvaloniaObject ao)
                 throw new InvalidOperationException("Styles can only be applied to AvaloniaObjects.");
 
             StyleInstance instance;
 
-            if (_sharedInstance is not null)
+            if (_sharedInstance is not null && canShareInstance)
             {
                 instance = _sharedInstance;
             }
             else
             {
-                var canShareInstance = activator is null;
+                canShareInstance &= activator is null;
 
                 instance = new StyleInstance(this, activator, type);
 


Test patch:
diff --git a/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs b/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs
index 52bee42d9d9..b44078caeb5 100644
--- a/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs
+++ b/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs
@@ -1029,6 +1029,28 @@ public void Animations_With_Activator_Trigger_Should_Be_Activated_And_Deactivate
             Assert.Equal(Brushes.Blue, border.Background);
         }
 
+        [Fact]
+        public void Should_Not_Share_Instance_When_Or_Selector_Is_Present()
+        {
+            // Issue #13910
+            Style style = new Style(x => Selectors.Or(x.OfType<Class1>(), x.OfType<Class2>().Class("bar")))
+            {
+                Setters =
+                {
+                    new Setter(Class1.FooProperty, "Foo"),
+                },
+            };
+
+            var target1 = new Class1 { Classes = { "foo" } };
+            var target2 = new Class2();
+
+            StyleHelpers.TryAttach(style, target1);
+            StyleHelpers.TryAttach(style, target2);
+
+            Assert.Equal("Foo", target1.Foo);
+            Assert.Equal("foodefault", target2.Foo);
+        }
+
         private class Class1 : Control
         {
             public static readonly StyledProperty<string> FooProperty =
@@ -1063,5 +1085,22 @@ protected override Size MeasureOverride(Size availableSize)
                 throw new NotImplementedException();
             }
         }
+
+        private class Class2 : Control
+        {
+            public static readonly StyledProperty<string> FooProperty =
+                Class1.FooProperty.AddOwner<Class2>();
+
+            public string Foo
+            {
+                get { return GetValue(FooProperty); }
+                set { SetValue(FooProperty, value); }
+            }
+
+            protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+            {
+                base.OnPropertyChanged(change);
+            }
+        }
     }
 }