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">
|
||||
Collapse
|
||||
</ToggleButton>
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Text="{ReflectionBinding #menu.SelectedItem.Header}" />
|
||||
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||
<TextBlock Text="{Binding SelectedMenuItem.Header}" />
|
||||
<Button Command="{Binding RandomCommand}">Random a selection</Button>
|
||||
</StackPanel>
|
||||
<Border
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
@@ -42,6 +42,7 @@
|
||||
IconBinding="{Binding IconIndex}"
|
||||
IsHorizontalCollapsed="{Binding #collapse.IsChecked, Mode=OneWay}"
|
||||
ItemsSource="{Binding MenuItems}"
|
||||
SelectedItem="{Binding SelectedMenuItem}"
|
||||
SubMenuBinding="{Binding Children}">
|
||||
<u:NavMenu.Styles>
|
||||
<Style x:DataType="vm:MenuItem" Selector="u|NavMenuItem">
|
||||
@@ -62,20 +63,20 @@
|
||||
</DataTemplate>
|
||||
</u:NavMenu.IconTemplate>
|
||||
<u:NavMenu.Header>
|
||||
<Grid ColumnDefinitions="Auto, Auto" HorizontalAlignment="Center">
|
||||
<Grid HorizontalAlignment="Center" ColumnDefinitions="Auto, Auto">
|
||||
<Image
|
||||
u:NavMenu.CanToggle="True"
|
||||
Width="48"
|
||||
Height="48"
|
||||
Margin="4 12"
|
||||
Margin="4,12"
|
||||
u:NavMenu.CanToggle="True"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="../Assets/Ursa.ico" />
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Classes="H5"
|
||||
VerticalAlignment="Center"
|
||||
Text="Ursa Avalonia"
|
||||
Classes="H5"
|
||||
IsVisible="{Binding !#menu.IsHorizontalCollapsed}"
|
||||
Text="Ursa Avalonia"
|
||||
Theme="{DynamicResource TitleTextBlock}" />
|
||||
</Grid>
|
||||
</u:NavMenu.Header>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
@@ -9,6 +10,13 @@ namespace Ursa.Demo.ViewModels;
|
||||
|
||||
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>
|
||||
{
|
||||
new MenuItem { Header = "Introduction" , Children =
|
||||
@@ -54,6 +62,30 @@ public class NavMenuDemoViewModel: ObservableObject
|
||||
new MenuItem { Header = "TwoTonePathIcon" },
|
||||
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
|
||||
@@ -77,4 +109,22 @@ public class 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.Reflection;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
@@ -164,7 +165,25 @@ public class NavMenu: ItemsControl
|
||||
|
||||
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)
|
||||
@@ -177,8 +196,11 @@ public class NavMenu: ItemsControl
|
||||
return new NavMenuItem();
|
||||
}
|
||||
|
||||
private bool _updateFromUI;
|
||||
|
||||
internal void SelectItem(NavMenuItem item, NavMenuItem parent)
|
||||
{
|
||||
_updateFromUI = true;
|
||||
// if (item.IsSelected) return;
|
||||
foreach (var child in LogicalChildren)
|
||||
{
|
||||
@@ -199,6 +221,34 @@ public class NavMenu: ItemsControl
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
protected void SelectItem(NavMenuItem item)
|
||||
internal void SelectItem(NavMenuItem item)
|
||||
{
|
||||
if (item == this)
|
||||
{
|
||||
@@ -329,4 +329,24 @@ public class NavMenuItem: HeaderedSelectingItemsControl
|
||||
|
||||
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