* Fix TextBox validation error persisting when reverting to same valid value
When a TwoWay binding with validation had an error and the user set the
target back to the same value that was last successfully written to the
source, WriteTargetValueToSource() would bail out early because the
target value matched LeafNode.Value. This prevented WriteValueToSource()
from being called, so the validation error was never cleared.
Add an ErrorType check to the condition in WriteTargetValueToSource() so
that the write-through still happens when there is a pending validation
error, matching the pattern already used in WriteValueToSource() at
line 310.
Fixes#20534https://claude.ai/code/session_01LTinLuE1bsNKaLPuDSNuuw
* Add test for validation error clearing when reverting to same valid value
Reproduces the scenario from #20534 where a TwoWay binding with a
setter that throws on invalid values fails to clear the validation error
when the target is set back to the same value that was last successfully
written to the source.
https://claude.ai/code/session_01LTinLuE1bsNKaLPuDSNuuw
* Remove redundant checks in WriteTargetValueToSource()
* Add failing test for #20688
Unit test created from issue description
* Add a failing test for wrong CacheLength handling
All items would be realized which is obviously wrong
* fix test setup used StackPanel instead of expcected
VirtualizingStackPanel
* Make sure the test actually fails
* update comment
* Fix for focusedElement and focusedIndex
* add another unit test
* Fixes for new test cases
* Addressing Review
* Update tests to match new behavior
* only recycle focused element if it is not null
* Address review
* Address copilot review
* add failing test
* fix StartU estimation
* remove unused sample file
* Implemented new drawn window decorations API
TODO: check if it works on Win32, bring back titlebar automation peer
* Adjusting naming a bit
* Naming / configuration changes
* Various fixes
* popover fix?
* wip
* Address review
* Extra window roles
* WIP
* Fixed drawn titlebar automation
* Purge ExtendClientAreaChromeHints.
* Fixed dynamically enabling drawn decorations
* api diff
* Add automation IDs for drawn decorations buttons
* Resolved the issues
* build
* Retry a few times when Pager isn't available after test is finished
* Only do faulty test detection if asked
* duplicate package reference
* Try disabling faulty tests on appium1
* Fix ExtendClientAreaWindowTests
* Apply initial button states
* Enable CSD shadow for X11
* net8?
* Address review
* more review comments
* Moar review comments
* Extra hit-test checks
* Moar review
* Prefix integration test app exitfullscreen to avoid clashes
* Disable drawn decorations if parts = None
* Respect SystemDecorations value on mac in extend-client-area mode
* Tidy up logic a bit
* Adjust win32 tests to titlebar not being in the tree when CSD are not enabled
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* move gesture events from Gestures to InputElement. Fix holding gesture interactions with context menu
* update api diff
* address review comments
* fix some test types
* rename Cancelled to Canceled
* update api diff
* Add failing test for font without head table
* Use a default DesignEmHeight if the font doesn't have one
* Add new font to Should_AddGlyphTypeface_By_Stream
* Add failing test for #20688
Unit test created from issue description
* Add a failing test for wrong CacheLength handling
All items would be realized which is obviously wrong
* fix test setup used StackPanel instead of expcected
VirtualizingStackPanel
* Make sure the test actually fails
* update comment
* Fix for focusedElement and focusedIndex
* add another unit test
* Fixes for new test cases
* Addressing Review
* Update tests to match new behavior
* only recycle focused element if it is not null
* Address review
* Address copilot review
* Make some overlay-related types/members internal
* Make sure that TopLevel is no longer the actual root of the visual tree. This is needed for our future changes.
* API diff
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fixed incorrect test
* Make automation to target FocusRoot
* api diff
* Hide WindowBase/EmbeddableControlRoot's parents from automation
* api diff
* Separate automation root and visual root for automation purposes
* Hide ChromeOverlayLayer from public API
* Synchronize WindowBase visibility to VisualRoot
* Hide WindowBase.ArrangeSetBounds
* api diff
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Handle font cmap format 13
* Fallback to last resort fonts as... a last resort
* Tests all fonts in Should_AddGlyphTypeface_By_Stream
* Add last resort font test
* Remove cmap subtable 13 from TestFontNoCmap412.ttf
* Onboard onto Central Package Management
* Remove SharpDX
* Add back <clear /> to NuGet.config package source mapping
* Package mapping
* Inline props where appropriate
* Lost a space
* Extracted IInputRoot out of TopLevel
* Move some input handling out of TopLevel
* Remove old class, make layout manager private
* Removed IRenderRoot
* Make VisualTreeAttachmentEventArgs a bit more sensible
* Move ILayoutRoot to PresentationSource
# Conflicts:
# tests/Avalonia.Controls.UnitTests/TabControlTests.cs
* Updated some VisualRoot / GetVisualRoot usages
* Updated more XxxRoot usages
* More Root usages
* Addressed review
* Hurr-durr xml
* More fixes
* Maybe fix android compilation
* API diff
* Yet another cast
* I had to use MSIL analysis to detect those casts
* Fixed automation
* Fix PointerOverPreProcessor
* Fix?
* Removed yet another cast to Visual
* The amount of random downcasts is astonishing
* Maybe fix mac
* Addressed review
* Native DockMenu code
* Add Native Interop
* Update ControlCatalog sample
* Add unit tests
* Add Action<IAvnMenu> to AvaloniaNativeMenuExporter
* Add dynamic dock item demo
* Move s_dockMenu reference to App
* Use Appium tests
* Revert INativeMenuExporterResetHandler
* Properly set the button for the checkbox
* Add dock test
* I hate Appium
* Rename NativeMenu.DockMenu to NativeDock.Menu
* Make static
* Remove Dock Click Test
* Add white space back for cleaner diff
* Reduce MenuExporter back to one
* Revert UpdateIfNeeded to private
* Revert QueueReset to private too... and fix some whitespace
* Revert IAvnMenuItem/IAvnMenu back
* That's what I get not comparing it to master
* And update this too
* Add documentation
* Add IMenuItem binding tests
* Use SetCurrentValue for all IMenuItem properties
Fix XMLDoc comments for MenuItem being inherited from an internal type
* Make binding plugin API internal.
Making everything pluggable like has performance implications even if the plugins are never customized (which will be the 99% case).
`IPropertyAccessor` is used in `CompiledBindingPathBuilder` so needs to be kept public for the moment.
* Disable Data Annotations validation by default.
It [conflicts with `CommunityToolkit.Mvvm`](https://github.com/AvaloniaUI/Avalonia/issues/8397) which is now the default MVVM framework, so require it to be enabled in the `AppBuilder`.
* Update API supressions.
* Add back missing using
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Find ancestors/descendants with a predicate
* Use Predicate instead of Func
* Find ancestors/descendants with a predicate
* Use Predicate instead of Func
* Predicate<Visual> to Predicate<T>
---------
Co-authored-by: Jan Kučera <miloush@users.noreply.github.com>
* Fire CaptureChanging event when source changes
* Do not notfiy platform if only source changed
* Notify ancestors of element to be captured if none yet
* Pointer capture notify on source change tests
---------
Co-authored-by: Jan Kučera <miloush@users.noreply.github.com>
* Reminder for future me.
* Move compiled bindings to Avalonia base.
* Update suppressions.
* Tweaked `BindingExpressionVisitor`.
And documented public (internal) API.
* Fix ncrunch config.
* Add comprehensive unit tests for BindingExpressionVisitor.
Tests cover all supported features including property access, indexers,
AvaloniaProperty access, logical NOT, stream bindings, and type operators.
Also includes tests for unsupported operations that should throw exceptions.
Discovered bug: IsAssignableFrom check at line 139 is backwards, causing
upcasts to incorrectly throw and downcasts to be incorrectly ignored.
Bug is documented with skipped tests showing expected behavior and passing
tests documenting current broken behavior.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Fix backwards IsAssignableFrom check in BindingExpressionVisitor.
Fixed the inheritance cast check which was inverted, causing:
- Upcasts (derived→base) to incorrectly throw exceptions
- Downcasts (base→derived) to be incorrectly ignored
Changed line 139 from:
node.Operand.Type.IsAssignableFrom(node.Type)
to:
node.Type.IsAssignableFrom(node.Operand.Type)
This correctly identifies safe upcasts (which are ignored) vs unsafe
downcasts (which throw exceptions).
Updated tests to remove skip attributes and removed the temporary tests
that documented the broken behavior. All 33 tests now pass.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Allow downcasts and all reference type casts in binding expressions.
Changed the cast handling to allow both upcasts and downcasts for reference
types. This makes casts actually useful in binding expressions while still
rejecting value type conversions that would require actual conversion logic.
The logic now checks:
- Both types must be reference types (not value types)
- One type must be assignable to/from the other (either direction)
This allows practical scenarios like:
- Upcasts: (BaseClass)derived
- Downcasts: (DerivedClass)baseInstance
- Casting through object: (TargetType)(object)source
The binding system will gracefully handle any runtime type mismatches.
Updated tests to verify downcasts are allowed and added test for casting
through object pattern.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Add clarifying test for cast transparency in binding expressions.
Added test showing that casts are transparent in property chains.
For example, ((TestClass)x).Property produces just one node for the
property access - the cast doesn't create additional nodes.
This clarifies that empty nodes for (TestClass)x is correct behavior:
- Empty nodes = bind to source directly
- The cast is just a type annotation, transparent to the binding path
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Fix: Casts should create ReflectionTypeCastNode, not be transparent.
Casts were incorrectly being treated as transparent (not creating nodes),
but CompiledBindingPath uses TypeCastPathElement which creates FuncTransformNode.
For consistency and correctness, BindingExpressionVisitor should also create
cast nodes using ReflectionTypeCastNode.
Changes:
- Convert expressions now create ReflectionTypeCastNode
- TypeAs expressions now create ReflectionTypeCastNode
- Both upcasts and downcasts create nodes (runtime checks handle failures)
Examples:
- x => (TestClass)x → 1 node (cast)
- x => ((TestClass)x).Prop → 2 nodes (cast + property)
- x => x.Child as object → 2 nodes (property + cast)
This matches the behavior of CompiledBindingPathBuilder.TypeCast<T>().
Updated all related tests to verify cast nodes are created.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Use compiled cast functions instead of reflection-based type checks.
Changed from ReflectionTypeCastNode (which uses Type.IsInstanceOfType) to
FuncTransformNode with a compiled cast function. This matches how
CompiledBindingPath handles TypeCastPathElement and provides better
performance by avoiding reflection.
The CreateCastFunc method compiles an expression `(object? obj) => obj as T`
which generates efficient IL similar to the 'is T' pattern used in
TypeCastPathElement<T>, rather than using reflection-based type checks.
Performance improvement:
- Before: Type.IsInstanceOfType() reflection call for each cast
- After: Compiled IL using 'as' operator (same as TypeCastPathElement<T>)
Updated tests to expect FuncTransformNode instead of ReflectionTypeCastNode.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Reuse TypeCastPathElement<T> cast function directly.
Instead of compiling our own cast expression, extract the Cast delegate
directly from TypeCastPathElement<T>. This ensures we use the exact same
code path as CompiledBindingPath, avoiding any potential behavioral
differences and code duplication.
Benefits:
- Code reuse - single implementation of cast logic
- Consistency - same behavior as CompiledBindingPathBuilder.TypeCast<T>()
- No duplicate expression compilation logic
Implementation uses reflection to create the closed generic type and
extract the pre-compiled Cast delegate, which is still more efficient
than reflection-based type checks at runtime.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Revert to lambda compilation approach for cast functions.
Reverted from using TypeCastPathElement<T> back to compiling lambda
expressions directly. The lambda approach is cleaner and more straightforward:
Benefits of lambda compilation:
- No Activator.CreateInstance call (avoids reflection for construction)
- More direct - creates exactly what we need
- No coupling to TypeCastPathElement internal implementation
- Simpler code flow
The compiled lambda generates the same efficient IL code (using 'as' operator)
as TypeCastPathElement<T> does, just without the indirection.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Code cleanup: Fix XML docs and remove unused usings.
- Changed CreateCastFunc XML docs to use <remarks> tag for better formatting
- Removed unused 'using Avalonia.Data;' from tests
- Removed redundant '#nullable enable' from tests
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Refactor BindingExpressionVisitor to use CompiledBindingPathBuilder.
Changes BindingExpressionVisitor to use CompiledBindingPathBuilder instead of
directly creating ExpressionNode instances, unifying the approach with
compile-time XAML bindings. Adds new BuildPath() method that returns
CompiledBindingPath, while maintaining backwards compatibility through the
existing BuildNodes() wrapper method.
Key changes:
- Replace internal List<ExpressionNode> with CompiledBindingPathBuilder
- Refactor all visitor methods to call builder methods
- Add accessor factory methods and implementations for property access
- Support AvaloniaProperty, CLR properties, arrays, indexers, streams, casts
- Update tests to expect PropertyAccessorNode, StreamNode, ArrayIndexerNode
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Remove CompiledBindingPathFromExpressionBuilder in favor of BindingExpressionVisitor.
Now that BindingExpressionVisitor has been refactored to use
CompiledBindingPathBuilder and provides a BuildPath() method, the test-only
CompiledBindingPathFromExpressionBuilder class is redundant and can be removed.
Changes:
- Replace CompiledBindingPathFromExpressionBuilder.Build() with
BindingExpressionVisitor<TIn>.BuildPath() in BindingExpressionTests
- Delete CompiledBindingPathFromExpressionBuilder.cs test file
- All 122 tests in BindingExpressionTests.Compiled continue to pass
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Move test-only methods from production code to test extensions.
Removes BindingExpression.Create and BindingExpressionVisitor.BuildNodes
from production code since they were only used by unit tests.
Changes:
- Remove BindingExpression.Create<TIn, TOut> method
- Remove BindingExpressionVisitor.BuildNodes method
- Add BindingExpressionVisitorExtensions in Base.UnitTests
- Add BindingExpressionExtensions in LeakTests
- Add static helper methods in test classes to reduce noise
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Add public CompiledBinding.Create factory methods from LINQ expressions.
Adds two static factory methods to create CompiledBinding instances from
lambda expressions using BindingExpressionVisitor.BuildPath():
- Create<TIn, TOut>(expression, converter, mode)
Creates binding without explicit source (uses DataContext)
- Create<TIn, TOut>(source, expression, converter, mode)
Creates binding with explicit source
This provides a type-safe, ergonomic API for creating compiled bindings
from code without string-based paths.
Usage:
var binding = CompiledBinding.Create(viewModel, vm => vm.Title);
textBlock.Bind(TextBlock.TextProperty, binding);
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* Merge CompiledBinding.Create overloads and add all binding property parameters.
Consolidates the two Create method overloads into a single method with source
as an optional parameter. Adds optional parameters for all CompiledBinding
properties (priority, converterCulture, converterParameter, fallbackValue,
stringFormat, targetNullValue, updateSourceTrigger, delay) per PR feedback.
Properties that default to AvaloniaProperty.UnsetValue (source, fallbackValue,
targetNullValue) use null-coalescing to convert null parameter values.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* (Re-)update suppressions.
* Add missing using.
* Fix ncrunch build.
* Remove file I committed by accident.
* PR feedback.
* Store static members outside generic class.
Based on PR feedback.
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* #19962 Add AXAML Source Information to debug Builds
* SimplifyXamlSourceInfo
* Add XamlSourceInfo for as many elements as possible
* Add tests to confirm XamlSourceInfo is set for all types
* Remove property only added for debugging during development
* update skipped test so it runs (even though it doesn't yet pass)
* Wrap XamlAstNewClrObjectNode instead of XamlAstObjectNode, run transformer late
* Remove unsupported value types from the More_Resources_Get_XamlSourceInfo_Set
* Fix Document property not being set in runtime parser
* Add a dedicated CreateSourceInfo parameter for RuntimeXamlLoaderConfiguration, instead of reusing DesignMode
* Inherit real XamlValueWithManipulationNode, move actual manipulation to a separate class
* Fix group transformers by unwrapping manipulation nodes first
* minor Resource related test change
* Update public API as agreed
* Add new failing tests for the dictionaries
* Fix randomly failing tests, that depend on the test order
* Fix assert
* Rename AvaloniaXamlResourceTransformer
* Emit XamlSourceInfo from AvaloniaXamlResourceTransformer
* Rename AvaloniaXamlIlResourceTransformer for consistency
* Cleanup comments
* Remove XamlSourceInfoValueWithManipulationNode, use standard XamlValueWithManipulationNode
* Add new RuntimeXamlLoaderDocument.Document property
* Use UriBuilder trick to support unix paths on windows
* Add private AttachedProperty for avalonia objects, instead of always using weak table
* Fix wrong UriBuilder usage and add more test assets
* Fix "Invalid URI" exception
---------
Co-authored-by: KimHenrik <kimhenrik@outlook.de>
Co-authored-by: Max Katz <maxkatz6@outlook.com>
* Introduce TextOptions API
* Store BaselinePixelAlignment as byte. Move to a dedicated file.
* Update API suppressions
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
* Introduce a universal IGlyphTypeface implementation that does not rely on any platform implementation
* Revert changes
* Fix Android
* Make the test happy
* Fix build
* Update baseline
* Fix naming
* Fix headless
* Move interfaces to dedicated files
Make GlyphTypeface.GlyphCount an integer
* Fix GlyphCount
* Make IGlyphTypeface NotClientImplementable
* Make sure we cache platform typefaces by their desired name, style, weight and stretch
* Update baseline
* Only use IGlyphTypeface
* Fix Android
* Try to clear the buffer before we encode somethimg
* Add needed test font
* Add more unit tests
* Reduce allocations
* Remove Direct2D1 test files
* More tests
* More complete table implementations
* More adjustments
* Use batch APIs
* Handle invalid timestamps
* Update baseline
* Introduce a CharacterToGlyphMap struct for faster access
* Remove AggressiveInlining
* Remove AggressiveInlining
* Make the head table optional for legacy fonts
* Remove Load method. Fix TextBlockTests
* Fix nullables
* Remove redundant folder
* Update Api baseline
* revert diff helper changes
* revert changes
* Use bare minimum font for Headless platform and introduce a test font manager that uses the Inter font for testing.
* Add missing font file for Headless platform
---------
Co-authored-by: Gillibald <stebner@avaloniaui.net>
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
Make LeafNode property nullable and return null when the binding expression
has no nodes (e.g., when using a constant source with a converter but no path).
This fixes an ArgumentOutOfRangeException that occurred when accessing
LeafNode or Description properties on such bindings.
Fixes#20441
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* Update to xunit.v3
* Little more progress
* More fixes
* Keep VSTest supported
* Adjust Nuke
* Few fixes
* Fix for xunit 2
* Fix GetData override
* Adjust
* Use MTP for xunit 2
* Fix test
* Better fix
* --no-progress
* Few more fixes
* no progress
* Fix test
* Better fix
* TRX
* Move to Directory.Build.props
* Unify on MTP v2
* Update
* Update to stable
* 1.0.1
* 1.0.2
* Fix some warnings
* Fix more warnings
* Fix more warnings
* Update ncrunch config.
* Tidy up reflection and multi-binding APIs:
- Move `BindingBase` and `MultiBinding` into Avalonia.Base
- `BindingBase` becomes a true base class for all bindings, and contains only the `Instance` method
- Properties common between reflection and compiled bindings are moved into `StandardBindingBase`
- `Binding` is moved to Avalonia.Base and renamed to `ReflectionBinding`
- A compatibility shim for `Binding` remains in Avalonia.Markup
- Remove `IBinding` and `IBinding2`
- Remove `ITreeDataTemplate's usage of `InstancedBinding`
- Remove `NativeMenuBarPresenter`s usage of `InstancedBinding`
- Remove `InstancedBinding` as it is now unused
This required an update to the DataGrid submodule: cell data validation has been temporarily removed as this used `InstancedBinding`.
* `Instance()` => `CreateInstance()`.
The use of "Instance" as a verb is quite unusual apparently ;)
* Seal classes where appropriate.
* Seal classes where appropriate.
* Remove `StandardBindingBase`.
Simply duplicate the members in reflection and compiled binding classes.
* Delete deleted submodule directory.
* Add missing attribute.
Fixes compile error.
* Fix reference to removed class.
* Update suppressions.