diff --git a/Documentation/build.md b/Documentation/build.md index fd6b26337c5..3fcaae8963f 100644 --- a/Documentation/build.md +++ b/Documentation/build.md @@ -14,6 +14,18 @@ git submodule update --init Go to https://dotnet.microsoft.com/download/visual-studio-sdks and install the latest version of the .NET Core SDK compatible with Avalonia UI. Make sure to download the SDK (not just the "runtime") package. The version compatible is indicated within the [global.json](https://github.com/AvaloniaUI/Avalonia/blob/master/global.json) file. Note that Avalonia UI does not always use the latest version and is hardcoded to use the last version known to be compatible (SDK releases may break the builds from time-to-time). +### Installing necessary .NET Workloads + +.NET SDK requires developers to install workloads for each platform they are targeting. +Since Avalonia targets pretty much every supported .NET platform, you need to install these workloads as well. +Running it from the command line: +``` +dotnet workload install android ios wasm-tools wasm-experimental +``` + +macOS workloads are not required to build Avalonia. +Note: on Unix OS you need to run this command from sudo. + ## Build and Run Avalonia ``` @@ -43,6 +55,25 @@ Build and run `ControlCatalog.NetCore` project to see the sample application. >CSC : error CS0006: Metadata file 'C:\...\Avalonia\packages\Avalonia\bin\Debug\netcoreapp2.0\Avalonia.dll' could not be found ``` To correct this, right click on the `Avalonia.DesktopRuntime` project then press `Build` to build the project manually. Afterwards the solution should build normally and the ControlCatalog can be run. + * **Error MSB4062 GenerateAvaloniaResourcesTask** + + Same as previous one, you need to manually build `Avalonia.Build.Tasks` project at least once. + + Alternatively, you can build the solution once with Nuke. + +## Building packages with Nuke + +Install Nuke +`dotnet tool install --global Nuke.GlobalTool --version 6.2.1` + +Build project: +`nuke --target Compile --configuration Release` + +And run tests: +`nuke --target RunTests --configuration Release` + +Or if you need to create nuget packages as well (it will compile and run tests automatically): +`nuke --target Package --configuration Release` # Linux/macOS diff --git a/readme.md b/readme.md index e9cd2207141..c9539e1eb9d 100644 --- a/readme.md +++ b/readme.md @@ -6,8 +6,6 @@
[![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) [![downloads](https://img.shields.io/nuget/dt/avalonia)](https://www.nuget.org/packages/Avalonia) ![Size](https://img.shields.io/github/repo-size/avaloniaui/avalonia.svg) -⚠️ **v11 Update - [Pausing community contributions](https://github.com/AvaloniaUI/Avalonia/discussions/10599)** - ## 📖 About [Avalonia](https://avaloniaui.net) is a cross-platform UI framework for dotnet, providing a flexible styling system and supporting a wide range of platforms such as Windows, macOS, Linux, iOS, Android and WebAssembly. Avalonia is mature and production ready and is used by companies, including [Schneider Electric](https://avaloniaui.net/showcase#se), [Unity](https://avaloniaui.net/showcase#unity), [JetBrains](https://avaloniaui.net/showcase#rider) and [Github](https://avaloniaui.net/showcase#github). diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml index a492808f1d0..b682ebf51de 100644 --- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml +++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml @@ -18,6 +18,10 @@ + + + + @@ -42,7 +46,6 @@ - diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs index d0b894101f2..ebf66164b73 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs @@ -1320,17 +1320,14 @@ private void TextUpdated(string? newText, bool userInitiated) // Evaluate the conditions needed for completion. // 1. Minimum prefix length // 2. If a delay timer is in use, use it - bool populateReady = newText.Length >= MinimumPrefixLength && MinimumPrefixLength >= 0; - if (populateReady && MinimumPrefixLength == 0 && String.IsNullOrEmpty(newText) && String.IsNullOrEmpty(SearchText)) - { - populateReady = false; - } - _userCalledPopulate = populateReady ? userInitiated : false; + bool minimumLengthReached = newText.Length >= MinimumPrefixLength && MinimumPrefixLength >= 0; + + _userCalledPopulate = minimumLengthReached && userInitiated; // Update the interface and values only as necessary UpdateTextValue(newText, userInitiated); - if (populateReady) + if (minimumLengthReached) { _ignoreTextSelectionChange = true; diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs index 785fd49983e..0002107ee0d 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/EventTreeNode.cs @@ -72,12 +72,13 @@ private void HandleEvent(object? sender, RoutedEventArgs e) var s = sender!; var handled = e.Handled; var route = e.Route; + var triggerTime = DateTime.Now; void handler() { if (_currentEvent == null || !_currentEvent.IsPartOfSameEventChain(e)) { - _currentEvent = new FiredEvent(e, new EventChainLink(s, handled, route)); + _currentEvent = new FiredEvent(e, new EventChainLink(s, handled, route), triggerTime); _parentViewModel.RecordedEvents.Add(_currentEvent); diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs index a9f3182bef8..1eab9afe8a2 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/FiredEvent.cs @@ -10,11 +10,12 @@ internal class FiredEvent : ViewModelBase private readonly RoutedEventArgs _eventArgs; private EventChainLink? _handledBy; - public FiredEvent(RoutedEventArgs eventArgs, EventChainLink originator) + public FiredEvent(RoutedEventArgs eventArgs, EventChainLink originator, DateTime triggerTime) { _eventArgs = eventArgs ?? throw new ArgumentNullException(nameof(eventArgs)); Originator = originator ?? throw new ArgumentNullException(nameof(originator)); AddToChain(originator); + TriggerTime = triggerTime; } public bool IsPartOfSameEventChain(RoutedEventArgs e) @@ -22,6 +23,8 @@ public bool IsPartOfSameEventChain(RoutedEventArgs e) return e == _eventArgs; } + public DateTime TriggerTime { get; } + public RoutedEvent Event => _eventArgs.RoutedEvent!; public bool IsHandled => HandledBy?.Handled == true; diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml index 54c2f067098..c18b8cf003e 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/EventsPageView.xaml @@ -77,21 +77,23 @@ - + - + + + - + - + diff --git a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs index acae583b5ca..f31df71c0d1 100644 --- a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs @@ -1,21 +1,15 @@ using System; -using System.Collections; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using Avalonia.Controls.Primitives; -using Avalonia.Controls.Presenters; using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Markup.Data; -using Avalonia.Platform; using Avalonia.Threading; using Avalonia.UnitTests; -using Moq; using Xunit; using System.Collections.ObjectModel; -using System.Reactive.Linq; using System.Reactive.Subjects; +using Avalonia.Input; namespace Avalonia.Controls.UnitTests { @@ -439,6 +433,29 @@ public void SelectedItem_Validation() }); } + [Fact] + public void Explicit_Dropdown_Open_Request_MinimumPrefixLength_0() + { + RunTest((control, textbox) => + { + control.Text = ""; + control.MinimumPrefixLength = 0; + Dispatcher.UIThread.RunJobs(); + + Assert.False(control.IsDropDownOpen); + + control.RaiseEvent(new KeyEventArgs + { + RoutedEvent = InputElement.KeyDownEvent, + Key = Key.Down + }); + + Dispatcher.UIThread.RunJobs(); + + Assert.True(control.IsDropDownOpen); + }); + } + /// /// Retrieves a defined predicate filter through a new AutoCompleteBox /// control instance. @@ -1072,14 +1089,14 @@ private void RunTest(Action test) private AutoCompleteBox CreateControl() { - var datePicker = + var autoCompleteBox = new AutoCompleteBox { Template = CreateTemplate() }; - datePicker.ApplyTemplate(); - return datePicker; + autoCompleteBox.ApplyTemplate(); + return autoCompleteBox; } private TextBox GetTextBox(AutoCompleteBox control) {