Merge pull request #701 from irihitech/navmenu

NavMenu: SelectionChanging Event
This commit is contained in:
Zhang Dian
2025-07-11 14:48:33 +08:00
committed by GitHub
8 changed files with 256 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Headless;
using Avalonia.Headless.XUnit;
using Avalonia.LogicalTree;
using Ursa.Controls;
namespace HeadlessTest.Ursa.Controls.NavMenuTests.CanSelectTests;
public class Test
{
[AvaloniaFact]
public void CanSelect_Blocks_Selection_Change_Inline_Xaml()
{
Window window = new Window
{
Width = 400,
Height = 400,
};
var view = new TestView1();
window.Content = view;
window.Show();
var menu = view.FindControl<NavMenu>("Menu");
var item1 = view.FindControl<NavMenuItem>("MenuItem1");
var item2 = view.FindControl<NavMenuItem>("MenuItem2");
var item3 = view.FindControl<NavMenuItem>("MenuItem3");
Assert.NotNull(menu);
Assert.NotNull(item1);
Assert.NotNull(item2);
Assert.NotNull(item3);
var point1 = item1.TranslatePoint(new Point(0, 0), window);
var point2 = item2.TranslatePoint(new Point(0, 0), window);
var point3 = item3.TranslatePoint(new Point(0, 0), window);
Assert.NotNull(point1);
Assert.NotNull(point2);
Assert.NotNull(point3);
window.MouseDown(new Point(point1.Value.X+10, point1.Value.Y+10), Avalonia.Input.MouseButton.Left);
window.MouseUp(new Point(point1.Value.X+10, point1.Value.Y+10), Avalonia.Input.MouseButton.Left);
Assert.Equal(item1, menu.SelectedItem);
window.MouseDown(new Point(point2.Value.X+10, point2.Value.Y+10), Avalonia.Input.MouseButton.Left);
window.MouseUp(new Point(point2.Value.X+10, point2.Value.Y+10), Avalonia.Input.MouseButton.Left);
Assert.Equal(item1, menu.SelectedItem); // Should not change selection due to CanSelect being false
window.MouseDown(new Point(point3.Value.X+10, point3.Value.Y+10), Avalonia.Input.MouseButton.Left);
window.MouseUp(new Point(point3.Value.X+10, point3.Value.Y+10), Avalonia.Input.MouseButton.Left);
Assert.Equal(item3, menu.SelectedItem); // Should change selection to item3
}
[AvaloniaFact]
public void CanSelect_Blocks_Selection_Change_Inline_Code()
{
Window window = new Window
{
Width = 400,
Height = 400,
};
var view = new TestView2();
window.Content = view;
window.Show();
var menu = view.FindControl<NavMenu>("Menu");
var items = menu.GetLogicalDescendants().OfType<NavMenuItem>().ToList();
var item1 = items[0];
var item2 = items[1];
var item3 = items[2];
Assert.NotNull(menu);
Assert.NotNull(item1);
Assert.NotNull(item2);
Assert.NotNull(item3);
var point1 = item1.TranslatePoint(new Point(0, 0), window);
var point2 = item2.TranslatePoint(new Point(0, 0), window);
var point3 = item3.TranslatePoint(new Point(0, 0), window);
Assert.NotNull(point1);
Assert.NotNull(point2);
Assert.NotNull(point3);
window.MouseDown(new Point(point1.Value.X+10, point1.Value.Y+10), Avalonia.Input.MouseButton.Left);
window.MouseUp(new Point(point1.Value.X+10, point1.Value.Y+10), Avalonia.Input.MouseButton.Left);
Assert.Equal(item1.DataContext, menu.SelectedItem);
window.MouseDown(new Point(point2.Value.X+10, point2.Value.Y+10), Avalonia.Input.MouseButton.Left);
window.MouseUp(new Point(point2.Value.X+10, point2.Value.Y+10), Avalonia.Input.MouseButton.Left);
Assert.Equal(item1.DataContext, menu.SelectedItem); // Should not change selection due to CanSelect being false
window.MouseDown(new Point(point3.Value.X+10, point3.Value.Y+10), Avalonia.Input.MouseButton.Left);
window.MouseUp(new Point(point3.Value.X+10, point3.Value.Y+10), Avalonia.Input.MouseButton.Left);
Assert.Equal(item3.DataContext, menu.SelectedItem); // Should change selection to item3
}
}

View File

@@ -0,0 +1,13 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="HeadlessTest.Ursa.Controls.NavMenuTests.CanSelectTests.TestView1">
<u:NavMenu Name="Menu" ExpandWidth="400" IsHorizontalCollapsed="False" SelectionChanging="Menu_OnSelectionChanging">
<u:NavMenuItem Name="MenuItem1" Header="Item 1" />
<u:NavMenuItem Name="MenuItem2" Header="Item 2" />
<u:NavMenuItem Name="MenuItem3" Header="Item 3" />
</u:NavMenu>
</UserControl>

View File

@@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Ursa.Controls;
namespace HeadlessTest.Ursa.Controls.NavMenuTests.CanSelectTests;
public partial class TestView1 : UserControl
{
public TestView1()
{
InitializeComponent();
}
private void Menu_OnSelectionChanging(object? sender, SelectionChangingEventArgs e)
{
var newItem = e.NewItems;
if (newItem is [NavMenuItem { Name: "MenuItem2" }])
{
e.CanSelect = false; // Prevent selection change for MenuItem2
}
}
}

View File

@@ -0,0 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa"
xmlns:canSelectTests="clr-namespace:HeadlessTest.Ursa.Controls.NavMenuTests.CanSelectTests"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="canSelectTests:TestView2ViewModel"
x:CompileBindings="True"
x:Class="HeadlessTest.Ursa.Controls.NavMenuTests.CanSelectTests.TestView2">
<u:NavMenu Name="Menu" ItemsSource="{Binding MenuItems}" SelectionChanging="NavMenu_OnSelectionChanging"/>
</UserControl>

View File

@@ -0,0 +1,43 @@
using System.Collections.ObjectModel;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using CommunityToolkit.Mvvm.ComponentModel;
using Ursa.Controls;
namespace HeadlessTest.Ursa.Controls.NavMenuTests.CanSelectTests;
public partial class TestView2 : UserControl
{
public TestView2()
{
InitializeComponent();
this.DataContext = new TestView2ViewModel();
}
private void NavMenu_OnSelectionChanging(object? sender, SelectionChangingEventArgs e)
{
if (e.NewItems is [MenuItemViewModel item])
{
if (item.Text.Contains("2"))
{
e.CanSelect = false;
}
}
}
}
public partial class TestView2ViewModel
{
public ObservableCollection<MenuItemViewModel> MenuItems { get; } = new()
{
new MenuItemViewModel { Text = "Menu Item 1" },
new MenuItemViewModel { Text = "Menu Item 2" },
new MenuItemViewModel { Text = "Menu Item 3" }
};
}
public partial class MenuItemViewModel: ObservableObject
{
[ObservableProperty] private string? _text;
}