feat: add function to set selected item from outside and sync to UI.
This commit is contained in:
@@ -26,10 +26,10 @@
|
|||||||
Grid.ColumnSpan="2">
|
Grid.ColumnSpan="2">
|
||||||
Collapse
|
Collapse
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
<TextBlock
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
Grid.Row="1"
|
<TextBlock Text="{Binding SelectedMenuItem.Header}" />
|
||||||
Grid.Column="0"
|
<Button Command="{Binding RandomCommand}">Random a selection</Button>
|
||||||
Text="{ReflectionBinding #menu.SelectedItem.Header}" />
|
</StackPanel>
|
||||||
<Border
|
<Border
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
IconBinding="{Binding IconIndex}"
|
IconBinding="{Binding IconIndex}"
|
||||||
IsHorizontalCollapsed="{Binding #collapse.IsChecked, Mode=OneWay}"
|
IsHorizontalCollapsed="{Binding #collapse.IsChecked, Mode=OneWay}"
|
||||||
ItemsSource="{Binding MenuItems}"
|
ItemsSource="{Binding MenuItems}"
|
||||||
|
SelectedItem="{Binding SelectedMenuItem}"
|
||||||
SubMenuBinding="{Binding Children}">
|
SubMenuBinding="{Binding Children}">
|
||||||
<u:NavMenu.Styles>
|
<u:NavMenu.Styles>
|
||||||
<Style x:DataType="vm:MenuItem" Selector="u|NavMenuItem">
|
<Style x:DataType="vm:MenuItem" Selector="u|NavMenuItem">
|
||||||
@@ -62,20 +63,20 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</u:NavMenu.IconTemplate>
|
</u:NavMenu.IconTemplate>
|
||||||
<u:NavMenu.Header>
|
<u:NavMenu.Header>
|
||||||
<Grid ColumnDefinitions="Auto, Auto" HorizontalAlignment="Center">
|
<Grid HorizontalAlignment="Center" ColumnDefinitions="Auto, Auto">
|
||||||
<Image
|
<Image
|
||||||
u:NavMenu.CanToggle="True"
|
|
||||||
Width="48"
|
Width="48"
|
||||||
Height="48"
|
Height="48"
|
||||||
Margin="4 12"
|
Margin="4,12"
|
||||||
|
u:NavMenu.CanToggle="True"
|
||||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||||
Source="../Assets/Ursa.ico" />
|
Source="../Assets/Ursa.ico" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Classes="H5"
|
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="Ursa Avalonia"
|
Classes="H5"
|
||||||
IsVisible="{Binding !#menu.IsHorizontalCollapsed}"
|
IsVisible="{Binding !#menu.IsHorizontalCollapsed}"
|
||||||
|
Text="Ursa Avalonia"
|
||||||
Theme="{DynamicResource TitleTextBlock}" />
|
Theme="{DynamicResource TitleTextBlock}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</u:NavMenu.Header>
|
</u:NavMenu.Header>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
@@ -9,6 +10,13 @@ namespace Ursa.Demo.ViewModels;
|
|||||||
|
|
||||||
public class NavMenuDemoViewModel: ObservableObject
|
public class NavMenuDemoViewModel: ObservableObject
|
||||||
{
|
{
|
||||||
|
private MenuItem? _selectedMenuItem;
|
||||||
|
|
||||||
|
public MenuItem? SelectedMenuItem
|
||||||
|
{
|
||||||
|
get=>_selectedMenuItem;
|
||||||
|
set => SetProperty(ref _selectedMenuItem, value);
|
||||||
|
}
|
||||||
public ObservableCollection<MenuItem> MenuItems { get; set; } = new ObservableCollection<MenuItem>
|
public ObservableCollection<MenuItem> MenuItems { get; set; } = new ObservableCollection<MenuItem>
|
||||||
{
|
{
|
||||||
new MenuItem { Header = "Introduction" , Children =
|
new MenuItem { Header = "Introduction" , Children =
|
||||||
@@ -54,6 +62,30 @@ public class NavMenuDemoViewModel: ObservableObject
|
|||||||
new MenuItem { Header = "TwoTonePathIcon" },
|
new MenuItem { Header = "TwoTonePathIcon" },
|
||||||
new MenuItem { Header = "ThemeToggler" }
|
new MenuItem { Header = "ThemeToggler" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public ICommand RandomCommand { get; set; }
|
||||||
|
public NavMenuDemoViewModel()
|
||||||
|
{
|
||||||
|
RandomCommand = new RelayCommand(OnRandom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRandom()
|
||||||
|
{
|
||||||
|
var items = GetLeaves();
|
||||||
|
var index = new Random().Next(items.Count);
|
||||||
|
SelectedMenuItem = items[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MenuItem> GetLeaves()
|
||||||
|
{
|
||||||
|
List<MenuItem> items = new();
|
||||||
|
foreach (var item in MenuItems)
|
||||||
|
{
|
||||||
|
items.AddRange(item.GetLeaves());
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MenuItem
|
public class MenuItem
|
||||||
@@ -77,4 +109,22 @@ public class MenuItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ObservableCollection<MenuItem> Children { get; set; } = new ObservableCollection<MenuItem>();
|
public ObservableCollection<MenuItem> Children { get; set; } = new ObservableCollection<MenuItem>();
|
||||||
|
|
||||||
|
public IEnumerable<MenuItem> GetLeaves()
|
||||||
|
{
|
||||||
|
if (this.Children.Count == 0)
|
||||||
|
{
|
||||||
|
yield return this;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var child in Children)
|
||||||
|
{
|
||||||
|
var items = child.GetLeaves();
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Metadata;
|
using Avalonia.Controls.Metadata;
|
||||||
@@ -164,7 +165,25 @@ public class NavMenu: ItemsControl
|
|||||||
|
|
||||||
private void OnSelectedItemChange(AvaloniaPropertyChangedEventArgs<object?> args)
|
private void OnSelectedItemChange(AvaloniaPropertyChangedEventArgs<object?> args)
|
||||||
{
|
{
|
||||||
Debug.WriteLine(args.NewValue.Value);
|
if (_updateFromUI) return;
|
||||||
|
var newValue = args.NewValue.Value;
|
||||||
|
if (newValue is null)
|
||||||
|
{
|
||||||
|
ClearAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var leaves = GetLeafMenus();
|
||||||
|
bool found = false;
|
||||||
|
foreach (var leaf in leaves)
|
||||||
|
{
|
||||||
|
if (leaf == newValue || leaf.DataContext == newValue)
|
||||||
|
{
|
||||||
|
leaf.SelectItem(leaf);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) return;
|
||||||
|
ClearAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||||
@@ -177,8 +196,11 @@ public class NavMenu: ItemsControl
|
|||||||
return new NavMenuItem();
|
return new NavMenuItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _updateFromUI;
|
||||||
|
|
||||||
internal void SelectItem(NavMenuItem item, NavMenuItem parent)
|
internal void SelectItem(NavMenuItem item, NavMenuItem parent)
|
||||||
{
|
{
|
||||||
|
_updateFromUI = true;
|
||||||
// if (item.IsSelected) return;
|
// if (item.IsSelected) return;
|
||||||
foreach (var child in LogicalChildren)
|
foreach (var child in LogicalChildren)
|
||||||
{
|
{
|
||||||
@@ -199,6 +221,34 @@ public class NavMenu: ItemsControl
|
|||||||
{
|
{
|
||||||
SelectedItem = item;
|
SelectedItem = item;
|
||||||
}
|
}
|
||||||
item.IsSelected = true;
|
item.BringIntoView();
|
||||||
|
// item.IsSelected = true;
|
||||||
|
_updateFromUI = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<NavMenuItem> GetLeafMenus()
|
||||||
|
{
|
||||||
|
foreach (var child in LogicalChildren)
|
||||||
|
{
|
||||||
|
if (child is NavMenuItem item)
|
||||||
|
{
|
||||||
|
var leafs = item.GetLeafMenus();
|
||||||
|
foreach (var leaf in leafs)
|
||||||
|
{
|
||||||
|
yield return leaf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearAll()
|
||||||
|
{
|
||||||
|
foreach (var child in LogicalChildren)
|
||||||
|
{
|
||||||
|
if (child is NavMenuItem item)
|
||||||
|
{
|
||||||
|
item.ClearSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,7 +265,7 @@ public class NavMenuItem: HeaderedSelectingItemsControl
|
|||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SelectItem(NavMenuItem item)
|
internal void SelectItem(NavMenuItem item)
|
||||||
{
|
{
|
||||||
if (item == this)
|
if (item == this)
|
||||||
{
|
{
|
||||||
@@ -329,4 +329,24 @@ public class NavMenuItem: HeaderedSelectingItemsControl
|
|||||||
|
|
||||||
return logical != null ? result : @default;
|
return logical != null ? result : @default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal IEnumerable<NavMenuItem> GetLeafMenus()
|
||||||
|
{
|
||||||
|
if (this.ItemCount == 0)
|
||||||
|
{
|
||||||
|
yield return this;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
foreach (var child in LogicalChildren)
|
||||||
|
{
|
||||||
|
if (child is NavMenuItem item)
|
||||||
|
{
|
||||||
|
var items = item.GetLeafMenus();
|
||||||
|
foreach (var i in items)
|
||||||
|
{
|
||||||
|
yield return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user