Browse Source

Fix TrayIcon menu crash (#16024)

* Updated the TrayIcon in IntegrationTestApp to have an associated menu.
Updated App.axaml.cs to set the DataContext for binding and provide a command implementation.
Added a project reference to Avalonia.ReactiveUI.

* Updated CanExecuteChanged in NativeMenuItem.cs to thunk to the UI thread if it ends up running on a non-UI thread.

* Replace ReactiveUI with MiniMvvm to simplify integration tests app

---------

Co-authored-by: Max Katz <maxkatz6@outlook.com>
pull/16159/head
Jonathan Gilbert 2 years ago
committed by GitHub
parent
commit
79f29ccae7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 22
      samples/IntegrationTestApp/App.axaml
  2. 16
      samples/IntegrationTestApp/App.axaml.cs
  3. 1
      samples/IntegrationTestApp/IntegrationTestApp.csproj
  4. 6
      src/Avalonia.Controls/NativeMenuItem.cs

22
samples/IntegrationTestApp/App.axaml

@ -1,13 +1,21 @@
<Application xmlns="https://github.com/avaloniaui" <Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="IntegrationTestApp.App"> xmlns:self="using:IntegrationTestApp"
x:Class="IntegrationTestApp.App"
x:DataType="self:App"
RequestedThemeVariant="Default">
<Application.Styles> <Application.Styles>
<FluentTheme /> <FluentTheme />
</Application.Styles> </Application.Styles>
<TrayIcon.Icons> <TrayIcon.Icons>
<TrayIcons> <TrayIcons>
<TrayIcon Icon="/Assets/icon.ico"> <TrayIcon Icon="/Assets/icon.ico">
</TrayIcon> <TrayIcon.Menu>
</TrayIcons> <NativeMenu>
</TrayIcon.Icons> <NativeMenuItem Header="Show _Test Window" Command="{Binding ShowWindowCommand}" />
</NativeMenu>
</TrayIcon.Menu>
</TrayIcon>
</TrayIcons>
</TrayIcon.Icons>
</Application> </Application>

16
samples/IntegrationTestApp/App.axaml.cs

@ -1,11 +1,25 @@
using System.Windows.Input;
using Avalonia; using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using MiniMvvm;
namespace IntegrationTestApp namespace IntegrationTestApp
{ {
public class App : Application public class App : Application
{ {
public App()
{
ShowWindowCommand = MiniCommand.Create(() =>
{
var window = new Window() { Title = "TrayIcon demo window" };
window.Show();
});
DataContext = this;
}
public override void Initialize() public override void Initialize()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
@ -20,5 +34,7 @@ namespace IntegrationTestApp
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();
} }
public ICommand ShowWindowCommand { get; }
} }
} }

1
samples/IntegrationTestApp/IntegrationTestApp.csproj

@ -25,6 +25,7 @@
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" /> <ProjectReference Include="..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

6
src/Avalonia.Controls/NativeMenuItem.cs

@ -5,6 +5,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Metadata; using Avalonia.Metadata;
using Avalonia.Threading;
using Avalonia.Utilities; using Avalonia.Utilities;
namespace Avalonia.Controls namespace Avalonia.Controls
@ -164,7 +165,10 @@ namespace Avalonia.Controls
void CanExecuteChanged() void CanExecuteChanged()
{ {
SetCurrentValue(IsEnabledProperty, Command?.CanExecute(CommandParameter) ?? true); if (!Dispatcher.UIThread.CheckAccess())
Dispatcher.UIThread.Invoke(() => CanExecuteChanged());
else
SetCurrentValue(IsEnabledProperty, Command?.CanExecute(CommandParameter) ?? true);
} }
public bool HasClickHandlers => Click != null; public bool HasClickHandlers => Click != null;

Loading…
Cancel
Save