Browse Source

Merge branch 'master' into features/NetAnalyzers/CA1304

Max Katz 2 years ago
parent
commit
ded16050b2
47 changed files with 139 additions and 106 deletions
  1. 8 0
      .editorconfig
  2. 12 3
      packages/Avalonia/AvaloniaBuildTasks.targets
  3. 3 0
      samples/Directory.Build.props
  4. 1 1
      src/Avalonia.Base/Animation/CrossFade.cs
  5. 1 1
      src/Avalonia.Base/CornerRadius.cs
  6. 3 2
      src/Avalonia.Base/Media/ArcSegment.cs
  7. 4 2
      src/Avalonia.Base/Media/BezierSegment .cs
  8. 4 4
      src/Avalonia.Base/Media/BoxShadow.cs
  9. 1 1
      src/Avalonia.Base/Media/Imaging/RenderTargetBitmap.cs
  10. 1 1
      src/Avalonia.Base/Media/Immutable/ImmutableTransform.cs
  11. 1 1
      src/Avalonia.Base/Media/Immutable/ImmutableVisualBrush.cs
  12. 4 2
      src/Avalonia.Base/Media/LineSegment.cs
  13. 1 1
      src/Avalonia.Base/Media/MatrixTransform.cs
  14. 1 1
      src/Avalonia.Base/Media/PathFigure.cs
  15. 1 1
      src/Avalonia.Base/Media/PathGeometry.cs
  16. 4 2
      src/Avalonia.Base/Media/QuadraticBezierSegment .cs
  17. 1 1
      src/Avalonia.Base/Media/RotateTransform.cs
  18. 1 1
      src/Avalonia.Base/Media/ScaleTransform.cs
  19. 1 1
      src/Avalonia.Base/Media/SkewTransform.cs
  20. 1 1
      src/Avalonia.Base/Media/Transform.cs
  21. 1 1
      src/Avalonia.Base/Media/TranslateTransform.cs
  22. 1 1
      src/Avalonia.Base/RelativePoint.cs
  23. 1 1
      src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs
  24. 1 1
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
  25. 1 1
      src/Avalonia.Base/Rendering/DeferredRenderer.cs
  26. 1 1
      src/Avalonia.Base/Rendering/RendererBase.cs
  27. 1 1
      src/Avalonia.Base/Rendering/SceneGraph/VisualNode.cs
  28. 1 1
      src/Avalonia.Base/Styling/Activators/IStyleActivator.cs
  29. 1 1
      src/Avalonia.Base/Thickness.cs
  30. 1 0
      src/Avalonia.Base/Visual.cs
  31. 1 1
      src/Avalonia.Base/VisualTree/TransformedBounds.cs
  32. 1 1
      src/Avalonia.Build.Tasks/Extensions.cs
  33. 1 1
      src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
  34. 1 1
      src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
  35. 1 1
      src/Avalonia.Controls/Selection/IndexRange.cs
  36. 2 2
      src/Avalonia.Controls/Selection/SelectionNodeBase.cs
  37. 13 7
      src/Avalonia.Controls/Slider.cs
  38. 1 1
      src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs
  39. 1 1
      src/Avalonia.DesignerSupport/Remote/HtmlTransport/SimpleWebSocketHttpServer.cs
  40. 1 1
      src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs
  41. 8 8
      src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml
  42. 19 20
      src/Avalonia.Themes.Fluent/Controls/Slider.xaml
  43. 9 9
      src/Avalonia.Themes.Simple/Controls/CalendarButton.xaml
  44. 10 10
      src/Browser/Avalonia.Browser/Cursor.cs
  45. 2 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
  46. 2 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/FindVisualAncestorNode.cs
  47. 2 2
      src/Windows/Avalonia.Win32/DirectX/DirectXStructs.cs

+ 8 - 0
.editorconfig

@@ -147,6 +147,14 @@ dotnet_diagnostic.CA1820.severity = warning
 dotnet_diagnostic.CA1821.severity = warning
 # CA1825: Avoid zero-length array allocations
 dotnet_diagnostic.CA1825.severity = warning
+# CA1826: Use property instead of Linq Enumerable method
+dotnet_diagnostic.CA1826.severity = suggestion
+# CA1827: Do not use Count/LongCount when Any can be used
+dotnet_diagnostic.CA1827.severity = warning
+# CA1828: Do not use CountAsync/LongCountAsync when AnyAsync can be used
+dotnet_diagnostic.CA1828.severity = warning
+# CA1829: Use Length/Count property instead of Enumerable.Count method
+dotnet_diagnostic.CA1829.severity = warning
 #CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
 dotnet_diagnostic.CA1847.severity = warning
 

+ 12 - 3
packages/Avalonia/AvaloniaBuildTasks.targets

@@ -30,7 +30,9 @@
              />
 
 
-  <Target Name="AddAvaloniaResources" BeforeTargets="ResolveReferences">
+  <Target Name="AddAvaloniaResources" 
+          BeforeTargets="ResolveReferences"
+          Condition="('@(AvaloniaResource->Count())' &gt; 0) or ('@(AvaloniaXaml->Count())' &gt; 0)">
     <PropertyGroup>
       <AvaloniaResourcesTemporaryFilePath Condition="'$(AvaloniaResourcesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/resources</AvaloniaResourcesTemporaryFilePath>
     </PropertyGroup>
@@ -62,7 +64,9 @@
           BeforeTargets="CoreCompile;CoreResGen"
           Inputs="@(AvaloniaResource);@(AvaloniaXaml);@(CustomAdditionalGenerateAvaloniaResourcesInputs);$(MSBuildAllProjects)"
           Outputs="$(AvaloniaResourcesTemporaryFilePath)"
-	  DependsOnTargets="$(BuildAvaloniaResourcesDependsOn)">
+          DependsOnTargets="$(BuildAvaloniaResourcesDependsOn)"
+          Condition="('@(AvaloniaResource->Count())' &gt; 0) or ('@(AvaloniaXaml->Count())' &gt; 0)"
+          >
     <ItemGroup>
         <AvaloniaResource Include="@(AvaloniaXaml)"/>
     </ItemGroup>
@@ -81,7 +85,12 @@
   <Target
     Name="CompileAvaloniaXaml"
     AfterTargets="AfterCompile"
-    Condition="Exists('@(IntermediateAssembly)') And $(DesignTimeBuild) != true And $(EnableAvaloniaXamlCompilation) != false"
+    Condition="
+      (('@(AvaloniaResource->Count())' &gt; 0) 
+          or ('@(AvaloniaXaml->Count())' &gt; 0))
+      and Exists('@(IntermediateAssembly)') 
+      And $(DesignTimeBuild) != true 
+      And $(EnableAvaloniaXamlCompilation) != false"
     >
     <PropertyGroup>
       <AvaloniaXamlReferencesTemporaryFilePath Condition="'$(AvaloniaXamlReferencesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/references</AvaloniaXamlReferencesTemporaryFilePath>

+ 3 - 0
samples/Directory.Build.props

@@ -4,4 +4,7 @@
       <AvaloniaPreviewerNetCoreToolPath>$(MSBuildThisFileDirectory)..\src\tools\Avalonia.Designer.HostApp\bin\Debug\netcoreapp2.0\Avalonia.Designer.HostApp.dll</AvaloniaPreviewerNetCoreToolPath>
   </PropertyGroup>
   <Import Project="..\build\SharedVersion.props" />
+  <PropertyGroup>
+    <EnableNETAnalyzers>false</EnableNETAnalyzers>
+  </PropertyGroup>  
 </Project>

+ 1 - 1
src/Avalonia.Base/Animation/CrossFade.cs

@@ -10,7 +10,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Animation
 {
     /// <summary>
-    /// Defines a cross-fade animation between two <see cref="IVisual"/>s.
+    /// Defines a cross-fade animation between two <see cref="Visual"/>s.
     /// </summary>
     public class CrossFade : IPageTransition
     {

+ 1 - 1
src/Avalonia.Base/CornerRadius.cs

@@ -100,7 +100,7 @@ namespace Avalonia
 
         public override string ToString()
         {
-            return $"{TopLeft},{TopRight},{BottomRight},{BottomLeft}";
+            return FormattableString.Invariant($"{TopLeft},{TopRight},{BottomRight},{BottomLeft}");
         }
 
         public static CornerRadius Parse(string s)

+ 3 - 2
src/Avalonia.Base/Media/ArcSegment.cs

@@ -1,3 +1,4 @@
+using System;
 using System.Globalization;
 
 namespace Avalonia.Media
@@ -100,6 +101,6 @@ namespace Avalonia.Media
         }
 
         public override string ToString()
-            => $"A {Size} {RotationAngle.ToString(CultureInfo.InvariantCulture)} {(IsLargeArc ? 1 : 0)} {(int)SweepDirection} {Point}";
+            => FormattableString.Invariant($"A {Size} {RotationAngle} {(IsLargeArc ? 1 : 0)} {(int)SweepDirection} {Point}");
     }
-}
+}

+ 4 - 2
src/Avalonia.Base/Media/BezierSegment .cs

@@ -1,3 +1,5 @@
+using System;
+
 namespace Avalonia.Media
 {
     public sealed class BezierSegment : PathSegment
@@ -60,6 +62,6 @@ namespace Avalonia.Media
         }
 
         public override string ToString()
-            => $"C {Point1} {Point2} {Point3}";
+            => FormattableString.Invariant($"C {Point1} {Point2} {Point3}");
     }
-}
+}

+ 4 - 4
src/Avalonia.Base/Media/BoxShadow.cs

@@ -94,22 +94,22 @@ namespace Avalonia.Media
 
             if (OffsetX != 0.0)
             {
-                sb.AppendFormat(" {0}", OffsetX.ToString());
+                sb.AppendFormat(" {0}", OffsetX.ToString(CultureInfo.InvariantCulture));
             }
 
             if (OffsetY != 0.0)
             {
-                sb.AppendFormat(" {0}", OffsetY.ToString());
+                sb.AppendFormat(" {0}", OffsetY.ToString(CultureInfo.InvariantCulture));
             }
             
             if (Blur != 0.0)
             {
-                sb.AppendFormat(" {0}", Blur.ToString());
+                sb.AppendFormat(" {0}", Blur.ToString(CultureInfo.InvariantCulture));
             }
 
             if (Spread != 0.0)
             {
-                sb.AppendFormat(" {0}", Spread.ToString());
+                sb.AppendFormat(" {0}", Spread.ToString(CultureInfo.InvariantCulture));
             }
 
             sb.AppendFormat(" {0}", Color.ToString());

+ 1 - 1
src/Avalonia.Base/Media/Imaging/RenderTargetBitmap.cs

@@ -7,7 +7,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media.Imaging
 {
     /// <summary>
-    /// A bitmap that holds the rendering of a <see cref="IVisual"/>.
+    /// A bitmap that holds the rendering of a <see cref="Visual"/>.
     /// </summary>
     public class RenderTargetBitmap : Bitmap, IDisposable, IRenderTarget
     {

+ 1 - 1
src/Avalonia.Base/Media/Immutable/ImmutableTransform.cs

@@ -3,7 +3,7 @@
 namespace Avalonia.Media.Immutable
 {
     /// <summary>
-    /// Represents a transform on an <see cref="IVisual"/>.
+    /// Represents a transform on an <see cref="Visual"/>.
     /// </summary>
     public class ImmutableTransform : ITransform
     {

+ 1 - 1
src/Avalonia.Base/Media/Immutable/ImmutableVisualBrush.cs

@@ -4,7 +4,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media.Immutable
 {
     /// <summary>
-    /// Paints an area with an <see cref="IVisual"/>.
+    /// Paints an area with an <see cref="Visual"/>.
     /// </summary>
     internal class ImmutableVisualBrush : ImmutableTileBrush, IVisualBrush
     {

+ 4 - 2
src/Avalonia.Base/Media/LineSegment.cs

@@ -1,3 +1,5 @@
+using System;
+
 namespace Avalonia.Media
 {
     public sealed class LineSegment : PathSegment
@@ -26,6 +28,6 @@ namespace Avalonia.Media
         }
 
         public override string ToString()
-            => $"L {Point}";
+            => FormattableString.Invariant($"L {Point}");
     }
-}
+}

+ 1 - 1
src/Avalonia.Base/Media/MatrixTransform.cs

@@ -4,7 +4,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media
 {
     /// <summary>
-    /// Transforms an <see cref="IVisual"/> according to a <see cref="Matrix"/>.
+    /// Transforms an <see cref="Visual"/> according to a <see cref="Matrix"/>.
     /// </summary>
     public class MatrixTransform : Transform
     {

+ 1 - 1
src/Avalonia.Base/Media/PathFigure.cs

@@ -126,7 +126,7 @@ namespace Avalonia.Media
         }
         
         public override string ToString()
-            => $"M {StartPoint} {string.Join(" ", _segments ?? Enumerable.Empty<PathSegment>())}{(IsClosed ? "Z" : "")}";
+            => FormattableString.Invariant($"M {StartPoint} {string.Join(" ", _segments ?? Enumerable.Empty<PathSegment>())}{(IsClosed ? "Z" : "")}");
 
         internal void ApplyTo(StreamGeometryContext ctx)
         {

+ 1 - 1
src/Avalonia.Base/Media/PathGeometry.cs

@@ -133,7 +133,7 @@ namespace Avalonia.Media
         public override string ToString()
         {
             var figuresString = _figures is not null ? string.Join(" ", _figures) : string.Empty;
-            return $"{(FillRule != FillRule.EvenOdd ? "F1 " : "")}{figuresString}";
+            return FormattableString.Invariant($"{(FillRule != FillRule.EvenOdd ? "F1 " : "")}{figuresString}");
         }
     }
 }

+ 4 - 2
src/Avalonia.Base/Media/QuadraticBezierSegment .cs

@@ -1,3 +1,5 @@
+using System;
+
 namespace Avalonia.Media
 {
     public sealed class QuadraticBezierSegment : PathSegment
@@ -44,6 +46,6 @@ namespace Avalonia.Media
         }
 
         public override string ToString()
-            => $"Q {Point1} {Point2}";
+            => FormattableString.Invariant($"Q {Point1} {Point2}");
     }
-}
+}

+ 1 - 1
src/Avalonia.Base/Media/RotateTransform.cs

@@ -4,7 +4,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media
 {
     /// <summary>
-    /// Rotates an <see cref="IVisual"/>.
+    /// Rotates an <see cref="Visual"/>.
     /// </summary>
     public class RotateTransform : Transform
     {

+ 1 - 1
src/Avalonia.Base/Media/ScaleTransform.cs

@@ -4,7 +4,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media
 {
     /// <summary>
-    /// Scale an <see cref="IVisual"/>.
+    /// Scale an <see cref="Visual"/>.
     /// </summary>
     public class ScaleTransform : Transform
     {

+ 1 - 1
src/Avalonia.Base/Media/SkewTransform.cs

@@ -4,7 +4,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media
 {
     /// <summary>
-    /// Skews an <see cref="IVisual"/>.
+    /// Skews an <see cref="Visual"/>.
     /// </summary>
     public class SkewTransform : Transform
     {

+ 1 - 1
src/Avalonia.Base/Media/Transform.cs

@@ -7,7 +7,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media
 {
     /// <summary>
-    /// Represents a transform on an <see cref="IVisual"/>.
+    /// Represents a transform on an <see cref="Visual"/>.
     /// </summary>
     public abstract class Transform : Animatable, IMutableTransform
     {

+ 1 - 1
src/Avalonia.Base/Media/TranslateTransform.cs

@@ -4,7 +4,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Media
 {
     /// <summary>
-    /// Translates (moves) an <see cref="IVisual"/>.
+    /// Translates (moves) an <see cref="Visual"/>.
     /// </summary>
     public class TranslateTransform : Transform
     {

+ 1 - 1
src/Avalonia.Base/RelativePoint.cs

@@ -199,7 +199,7 @@ namespace Avalonia
         {
             return _unit == RelativeUnit.Absolute ?
                 _point.ToString() :
-                 string.Format(CultureInfo.InvariantCulture, "{0}%, {1}%", _point.X * 100, _point.Y * 100);
+                string.Format(CultureInfo.InvariantCulture, "{0}%, {1}%", _point.X * 100, _point.Y * 100);
         }
     }
 }

+ 1 - 1
src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs

@@ -52,7 +52,7 @@ internal class FpsCounter
             _lastFpsUpdate = now;
         }
 
-        var fpsLine = $"Frame #{_totalFrames:00000000} FPS: {_fps:000} " + aux;
+        var fpsLine = FormattableString.Invariant($"Frame #{_totalFrames:00000000} FPS: {_fps:000} ") + aux;
         double width = 0;
         double height = 0;
         foreach (var ch in fpsLine)

+ 1 - 1
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs

@@ -156,7 +156,7 @@ namespace Avalonia.Rendering.Composition.Server
                         (Compositor.BatchObjectPool.CurrentUsage + Compositor.BatchObjectPool.CurrentPool) *
                                                                      Compositor.BatchObjectPool.ArraySize *
                                                                      IntPtr.Size), false);
-                    _fpsCounter.RenderFps(targetContext, $"M:{managedMem} / N:{nativeMem} R:{RenderedVisuals:0000}");
+                    _fpsCounter.RenderFps(targetContext, FormattableString.Invariant($"M:{managedMem} / N:{nativeMem} R:{RenderedVisuals:0000}"));
                 }
                 RenderedVisuals = 0;
 

+ 1 - 1
src/Avalonia.Base/Rendering/DeferredRenderer.cs

@@ -725,7 +725,7 @@ namespace Avalonia.Rendering
 
             foreach (var layer in Layers)
             {
-                var fileName = Path.Combine(DebugFramesPath ?? string.Empty, $"frame-{id}-layer-{index++}.png");
+                var fileName = Path.Combine(DebugFramesPath ?? string.Empty, FormattableString.Invariant($"frame-{id}-layer-{index++}.png"));
                 layer.Bitmap.Item.Save(fileName);
             }
         }

+ 1 - 1
src/Avalonia.Base/Rendering/RendererBase.cs

@@ -36,7 +36,7 @@ namespace Avalonia.Rendering
                 _lastFpsUpdate = now;
             }
 
-            var text = layerCount.HasValue ? $"Layers: {layerCount} FPS: {_fps:000}" : $"FPS: {_fps:000}";
+            var text = layerCount.HasValue ? FormattableString.Invariant($"Layers: {layerCount} FPS: {_fps:000}") : FormattableString.Invariant($"FPS: {_fps:000}");
 
             var formattedText = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, Typeface.Default, s_fontSize, Brushes.White);
 

+ 1 - 1
src/Avalonia.Base/Rendering/SceneGraph/VisualNode.cs

@@ -10,7 +10,7 @@ using Avalonia.VisualTree;
 namespace Avalonia.Rendering.SceneGraph
 {
     /// <summary>
-    /// A node in the low-level scene graph representing an <see cref="IVisual"/>.
+    /// A node in the low-level scene graph representing an <see cref="Visual"/>.
     /// </summary>
     internal class VisualNode : IVisualNode
     {

+ 1 - 1
src/Avalonia.Base/Styling/Activators/IStyleActivator.cs

@@ -39,7 +39,7 @@ namespace Avalonia.Styling.Activators
         /// </summary>
         /// <param name="sink">The listener.</param>
         /// <remarks>
-        /// This method should not call <see cref="IStyleActivatorSink.OnNext(bool, int)"/>.
+        /// This method should not call <see cref="IStyleActivatorSink.OnNext(bool)"/>.
         /// </remarks>
         void Subscribe(IStyleActivatorSink sink);
 

+ 1 - 1
src/Avalonia.Base/Thickness.cs

@@ -277,7 +277,7 @@ namespace Avalonia
         /// <returns>The string representation of the thickness.</returns>
         public override string ToString()
         {
-            return $"{_left},{_top},{_right},{_bottom}";
+            return FormattableString.Invariant($"{_left},{_top},{_right},{_bottom}");
         }
 
         /// <summary>

+ 1 - 0
src/Avalonia.Base/Visual.cs

@@ -417,6 +417,7 @@ namespace Avalonia
             OnAttachedToVisualTree(e);
             AttachedToVisualTree?.Invoke(this, e);
             InvalidateVisual();
+            _visualRoot.Renderer?.RecalculateChildren(_visualParent!);
 
             if (ZIndex != 0 && VisualParent is Visual parent)
                 parent.HasNonUniformZIndexChildren = true;

+ 1 - 1
src/Avalonia.Base/VisualTree/TransformedBounds.cs

@@ -77,6 +77,6 @@ namespace Avalonia.VisualTree
             return !left.Equals(right);
         }
 
-        public override string ToString() => $"Bounds: {Bounds} Clip: {Clip} Transform {Transform}";
+        public override string ToString() => FormattableString.Invariant($"Bounds: {Bounds} Clip: {Clip} Transform {Transform}");
     }
 }

+ 1 - 1
src/Avalonia.Build.Tasks/Extensions.cs

@@ -5,7 +5,7 @@ namespace Avalonia.Build.Tasks
 {
     static class Extensions
     {
-        static string FormatErrorCode(BuildEngineErrorCode code) => $"AVLN:{(int)code:0000}";
+        static string FormatErrorCode(BuildEngineErrorCode code) => FormattableString.Invariant($"AVLN:{(int)code:0000}");
 
         public static void LogError(this IBuildEngine engine, BuildEngineErrorCode code, string file, Exception ex,
             int lineNumber = 0, int linePosition = 0)

+ 1 - 1
src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs

@@ -67,7 +67,7 @@ namespace Avalonia.Build.Tasks
            {
               
                var src = new Source(r.ItemSpec, Root);
-               BuildEngine.LogMessage($"avares -> name:{src.Path}, path: {src.SystemPath}, size:{src.Size}, ItemSpec:{r.ItemSpec}", _reportImportance);
+               BuildEngine.LogMessage(FormattableString.Invariant($"avares -> name:{src.Path}, path: {src.SystemPath}, size:{src.Size}, ItemSpec:{r.ItemSpec}"), _reportImportance);
                return src;
            }).ToList();
 

+ 1 - 1
src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs

@@ -259,7 +259,7 @@ namespace Avalonia.Controls.Primitives
                 SelectedValue = (int)newSel * Increment + MinimumValue;
                 _suppressUpdateOffset = false;
 
-                System.Diagnostics.Debug.WriteLine($"Offset: {_offset} ItemHeight: {ItemHeight}");
+                System.Diagnostics.Debug.WriteLine(FormattableString.Invariant($"Offset: {_offset} ItemHeight: {ItemHeight}"));
             }
         }
 

+ 1 - 1
src/Avalonia.Controls/Selection/IndexRange.cs

@@ -86,7 +86,7 @@ namespace Avalonia.Controls.Selection
             return hashCode;
         }
 
-        public override string ToString() => $"[{Begin}..{End}]";
+        public override string ToString() => FormattableString.Invariant($"[{Begin}..{End}]");
 
         public static bool operator ==(IndexRange left, IndexRange right) => left.Equals(right);
         public static bool operator !=(IndexRange left, IndexRange right) => !(left == right);

+ 2 - 2
src/Avalonia.Controls/Selection/SelectionNodeBase.cs

@@ -290,12 +290,12 @@ namespace Avalonia.Controls.Selection
             // so bail.
             //
             // See unit test Handles_Selection_Made_In_CollectionChanged for more details.
-            if (ItemsView is object &&
+            if (ItemsView is not null &&
                 RangesEnabled &&
                 Ranges.Count > 0 &&
                 e.Action == NotifyCollectionChangedAction.Add)
             {
-                var lastIndex = Ranges.Last().End;
+                var lastIndex = Ranges[Ranges.Count - 1].End;
 
                 if (e.NewStartingIndex <= lastIndex)
                 {

+ 13 - 7
src/Avalonia.Controls/Slider.cs

@@ -190,7 +190,7 @@ namespace Avalonia.Controls
             _increaseButtonSubscription?.Dispose();
             _increaseButtonReleaseDispose?.Dispose();
             _pointerMovedDispose?.Dispose();
-            
+
             _decreaseButton = e.NameScope.Find<Button>("PART_DecreaseButton");
             _track = e.NameScope.Find<Track>("PART_Track");
             _increaseButton = e.NameScope.Find<Button>("PART_IncreaseButton");
@@ -258,7 +258,7 @@ namespace Avalonia.Controls
 
             e.Handled = handled;
         }
-            
+
         private void MoveToNextTick(double direction)
         {
             if (direction == 0.0) return;
@@ -317,6 +317,12 @@ namespace Avalonia.Controls
 
         private void TrackMoved(object? sender, PointerEventArgs e)
         {
+            if (!IsEnabled)
+            {
+                _isDragging = false;
+                return;
+            }
+
             if (_isDragging)
             {
                 MoveToPoint(e.GetCurrentPoint(_track));
@@ -343,15 +349,15 @@ namespace Avalonia.Controls
                 return;
 
             var orient = Orientation == Orientation.Horizontal;
-            var thumbLength = (orient 
-                ? _track.Thumb.Bounds.Width 
+            var thumbLength = (orient
+                ? _track.Thumb.Bounds.Width
                 : _track.Thumb.Bounds.Height) + double.Epsilon;
-            var trackLength = (orient 
-                ? _track.Bounds.Width 
+            var trackLength = (orient
+                ? _track.Bounds.Width
                 : _track.Bounds.Height) - thumbLength;
             var trackPos = orient ? posOnTrack.Position.X : posOnTrack.Position.Y;
             var logicalPos = MathUtilities.Clamp((trackPos - thumbLength * 0.5) / trackLength, 0.0d, 1.0d);
-            var invert = orient ? 
+            var invert = orient ?
                 IsDirectionReversed ? 1 : 0 :
                 IsDirectionReversed ? 0 : 1;
             var calcVal = Math.Abs(invert - logicalPos);

+ 1 - 1
src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs

@@ -162,7 +162,7 @@ namespace Avalonia.DesignerSupport.Remote.HtmlTransport
                     if (sendNow != null && socket != null)
                     {
                         await socket.SendMessage(
-                            $"frame:{sendNow.SequenceId}:{sendNow.Width}:{sendNow.Height}:{sendNow.Stride}:{sendNow.DpiX}:{sendNow.DpiY}");
+                            FormattableString.Invariant($"frame:{sendNow.SequenceId}:{sendNow.Width}:{sendNow.Height}:{sendNow.Stride}:{sendNow.DpiX}:{sendNow.DpiY}"));
                         await socket.SendMessage(false, sendNow.Data);
                     }
 

+ 1 - 1
src/Avalonia.DesignerSupport/Remote/HtmlTransport/SimpleWebSocketHttpServer.cs

@@ -146,7 +146,7 @@ namespace Avalonia.DesignerSupport.Remote.HtmlTransport
 
         public async Task RespondAsync(int code, byte[] data, string contentType)
         {
-            var headers = Encoding.UTF8.GetBytes($"HTTP/1.1 {code} {(HttpStatusCode)code}\r\nConnection: close\r\nContent-Type: {contentType}\r\nContent-Length: {data.Length}\r\n\r\n");
+            var headers = Encoding.UTF8.GetBytes(FormattableString.Invariant($"HTTP/1.1 {code} {(HttpStatusCode)code}\r\nConnection: close\r\nContent-Type: {contentType}\r\nContent-Length: {data.Length}\r\n\r\n"));
             await _stream.WriteAsync(headers, 0, headers.Length);
             await _stream.WriteAsync(data, 0, data.Length);
             _stream.Dispose();

+ 1 - 1
src/Avalonia.FreeDesktop/DBusTrayIconImpl.cs

@@ -127,7 +127,7 @@ namespace Avalonia.FreeDesktop
             var pid = Process.GetCurrentProcess().Id;
             var tid = s_trayIconInstanceId++;
 
-            _sysTrayServiceName = $"org.kde.StatusNotifierItem-{pid}-{tid}";
+            _sysTrayServiceName = FormattableString.Invariant($"org.kde.StatusNotifierItem-{pid}-{tid}");
             _statusNotifierItemDbusObj = new StatusNotifierItemDbusObj(_dbusMenuPath);
 
             try

+ 8 - 8
src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml

@@ -35,13 +35,13 @@
           <!-- To mimic WinUI SystemFocusVisual, Focus visual is drawn outside the bounds of the item -->
           <Border Name="Root" Background="{TemplateBinding Background}"
                   BorderThickness="0" ClipToBounds="True">
-            <ContentControl Name="Content"
-                            ContentTemplate="{TemplateBinding ContentTemplate}"
-                            Content="{TemplateBinding Content}"
-                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
-                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
-                            FontSize="{TemplateBinding FontSize}"
-                            Margin="{TemplateBinding Padding}" />
+            <ContentPresenter Name="Content"
+                              ContentTemplate="{TemplateBinding ContentTemplate}"
+                              Content="{TemplateBinding Content}"
+                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
+                              FontSize="{TemplateBinding FontSize}"
+                              Margin="{TemplateBinding Padding}" />
           </Border>
 
           <!-- Drawn Border should render on top of background to preserve the 1px margin between items -->
@@ -70,7 +70,7 @@
         <Setter Property="BorderBrush" Value="{DynamicResource CalendarViewSelectedBorderBrush}" />
       </Style>
 
-      <Style Selector="^ /template/ ContentControl#Content">
+      <Style Selector="^ /template/ ContentPresenter#Content">
         <Setter Property="Foreground" Value="{DynamicResource CalendarViewTodayForeground}" />
         <Setter Property="FontWeight" Value="SemiBold" />
       </Style>

+ 19 - 20
src/Avalonia.Themes.Fluent/Controls/Slider.xaml

@@ -302,26 +302,6 @@
       <Setter Property="IsVisible" Value="True" />
     </Style>
 
-    <!--  Disabled State  -->
-
-    <Style Selector="^:disabled">
-      <Style Selector="^ /template/ RepeatButton#PART_DecreaseButton">
-        <Setter Property="Background" Value="{DynamicResource SliderTrackValueFillDisabled}" />
-      </Style>
-
-      <Style Selector="^ /template/ RepeatButton#PART_IncreaseButton">
-        <Setter Property="Background" Value="{DynamicResource SliderTrackFillDisabled}" />
-      </Style>
-
-      <Style Selector="^ /template/ Thumb">
-        <Setter Property="Background" Value="{DynamicResource SliderThumbBackgroundDisabled}" />
-      </Style>
-
-      <Style Selector="^ /template/ TickBar">
-        <Setter Property="Fill" Value="{DynamicResource SliderTickBarFillDisabled}" />
-      </Style>
-    </Style>
-
     <!--  PointerOver State  -->
     <Style Selector="^:pointerover">
       <Style Selector="^ /template/ Grid#SliderContainer">
@@ -362,6 +342,25 @@
       </Style>
     </Style>
 
+    <!--  Disabled State  -->
+    <Style Selector="^:disabled">
+      <Style Selector="^ /template/ RepeatButton#PART_DecreaseButton">
+        <Setter Property="Background" Value="{DynamicResource SliderTrackValueFillDisabled}" />
+      </Style>
+
+      <Style Selector="^ /template/ RepeatButton#PART_IncreaseButton">
+        <Setter Property="Background" Value="{DynamicResource SliderTrackFillDisabled}" />
+      </Style>
+
+      <Style Selector="^ /template/ Thumb">
+        <Setter Property="Background" Value="{DynamicResource SliderThumbBackgroundDisabled}" />
+      </Style>
+
+      <Style Selector="^ /template/ TickBar">
+        <Setter Property="Fill" Value="{DynamicResource SliderTickBarFillDisabled}" />
+      </Style>
+    </Style>
+
     <Style Selector="^:error">
       <Setter Property="Foreground" Value="{DynamicResource SystemControlErrorTextForegroundBrush}" />
       <Style Selector="^ /template/ Thumb">

+ 9 - 9
src/Avalonia.Themes.Simple/Controls/CalendarButton.xaml

@@ -32,14 +32,14 @@
                      Opacity="0.5" />
 
           <!--  Focusable="False"  -->
-          <ContentControl Name="Content"
-                          Margin="1,0,1,1"
-                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
-                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
-                          Content="{TemplateBinding Content}"
-                          ContentTemplate="{TemplateBinding ContentTemplate}"
-                          FontSize="{TemplateBinding FontSize}"
-                          Foreground="{TemplateBinding Foreground}" />
+          <ContentPresenter Name="Content"
+                            Margin="1,0,1,1"
+                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
+                            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
+                            Content="{TemplateBinding Content}"
+                            ContentTemplate="{TemplateBinding ContentTemplate}"
+                            FontSize="{TemplateBinding FontSize}"
+                            Foreground="{TemplateBinding Foreground}" />
 
           <Rectangle Name="FocusVisual"
                      IsHitTestVisible="False"
@@ -62,7 +62,7 @@
       <Setter Property="IsVisible" Value="True" />
     </Style>
 
-    <Style Selector="^:inactive /template/ ContentControl#Content">
+    <Style Selector="^:inactive /template/ ContentPresenter#Content">
       <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLowBrush}" />
     </Style>
 

+ 10 - 10
src/Browser/Avalonia.Browser/Cursor.cs

@@ -20,9 +20,9 @@ namespace Avalonia.Browser
         /// </summary>
         public CssCursor(string base64, string format, PixelPoint hotspot, StandardCursorType fallback)
         {
-            Value = $"url(\"data:image/{format};base64,{base64}\") {hotspot.X} {hotspot.Y}, {ToKeyword(fallback)}";
+            Value = FormattableString.Invariant($"url(\"data:image/{format};base64,{base64}\") {hotspot.X} {hotspot.Y}, {ToKeyword(fallback)}");
         }
-        
+
         /// <summary>
         /// Create a cursor from url to *.cur file.
         /// </summary>
@@ -30,15 +30,15 @@ namespace Avalonia.Browser
         {
             Value = $"url('{url}'), {ToKeyword(fallback)}";
         }
-        
+
         /// <summary>
         /// Create a cursor from png/svg and hotspot position
         /// </summary>
         public CssCursor(string url, PixelPoint hotSpot, StandardCursorType fallback)
         {
-            Value = $"url('{url}') {hotSpot.X} {hotSpot.Y}, {ToKeyword(fallback)}";
+            Value = FormattableString.Invariant($"url('{url}') {hotSpot.X} {hotSpot.Y}, {ToKeyword(fallback)}");
         }
-        
+
         private static string ToKeyword(StandardCursorType type) => type switch
         {
             StandardCursorType.Hand => "pointer",
@@ -49,16 +49,16 @@ namespace Avalonia.Browser
             StandardCursorType.None => "none",
             StandardCursorType.Wait => "progress",
             StandardCursorType.AppStarting => "wait",
-            
+
             StandardCursorType.DragMove => "move",
             StandardCursorType.DragCopy => "copy",
             StandardCursorType.DragLink => "alias",
-            
+
             StandardCursorType.UpArrow => "default",/*not found matching one*/
             StandardCursorType.SizeWestEast => "ew-resize",
             StandardCursorType.SizeNorthSouth => "ns-resize",
             StandardCursorType.SizeAll => "move",
-            
+
             StandardCursorType.TopSide => "n-resize",
             StandardCursorType.BottomSide => "s-resize",
             StandardCursorType.LeftSide => "w-resize",
@@ -67,10 +67,10 @@ namespace Avalonia.Browser
             StandardCursorType.TopRightCorner => "ne-resize",
             StandardCursorType.BottomLeftCorner => "sw-resize",
             StandardCursorType.BottomRightCorner => "se-resize",
-            
+
             _ => Default,
         };
-        
+
         public void Dispose() {}
     }
 

+ 2 - 2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs

@@ -275,7 +275,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
         public int Level { get; }
 
         public override string ToString()
-           => $"$parent[{AncestorType?.Name},{Level}]";
+           => FormattableString.Invariant($"$parent[{AncestorType?.Name},{Level}]");
     }
 
     internal class VisualAncestorPathElement : ICompiledBindingPathElement, IControlSourceBindingPathElement
@@ -316,7 +316,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
         public int[] Indices { get; }
         public Type ElementType { get; }
         public override string ToString()
-            => $"[{string.Join(",", Indices)}]";
+            => FormattableString.Invariant($"[{string.Join(",", Indices)}]");
     }
 
     internal class TypeCastPathElement<T> : ITypeCastElement

+ 2 - 2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/FindVisualAncestorNode.cs

@@ -22,11 +22,11 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
             {
                 if (_ancestorType == null)
                 {
-                    return $"$visualparent[{_level}]";
+                    return FormattableString.Invariant($"$visualparent[{_level}]");
                 }
                 else
                 {
-                    return $"$visualparent[{_ancestorType.Name}, {_level}]";
+                    return FormattableString.Invariant($"$visualparent[{_ancestorType.Name}, {_level}]");
                 }
             }
         }

+ 2 - 2
src/Windows/Avalonia.Win32/DirectX/DirectXStructs.cs

@@ -1245,7 +1245,7 @@ namespace Avalonia.Win32.DxgiSwapchain
 
         internal RECT DesktopCoordinates;
 
-        internal bool AttachedToDesktop;
+        internal int AttachedToDesktop; // BOOL maps to int. If we use the CLR 'bool' type here, the struct becomes non-blittable. See #9599
 
         internal DXGI_MODE_ROTATION Rotation;
 
@@ -1323,7 +1323,7 @@ namespace Avalonia.Win32.DxgiSwapchain
         public uint Width;
         public uint Height;
         public DXGI_FORMAT Format;
-        public bool Stereo;
+        public int Stereo; // BOOL maps to int. If we use the CLR 'bool' type here, the struct becomes non-blittable. See #9599
         public DXGI_SAMPLE_DESC SampleDesc;
         public uint BufferUsage;
         public uint BufferCount;