From 64d5c967a9c9d1a66f23a09575be981eb3380c22 Mon Sep 17 00:00:00 2001 From: Lubomir Tetak Date: Mon, 25 Oct 2021 10:33:19 +0200 Subject: [PATCH 01/10] DevTools - allow to navigate to children (especially DataContext) (cherry picked from commit 4f89fd5f4d1ec390e5eb20b6c7979e0229151d12) --- .../ViewModels/ControlDetailsViewModel.cs | 132 ++++++++++++++---- .../Diagnostics/Views/ControlDetailsView.xaml | 17 ++- .../Views/ControlDetailsView.xaml.cs | 11 ++ 3 files changed, 130 insertions(+), 30 deletions(-) diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs index 3790951b0c..d3f07d09e1 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs @@ -17,42 +17,26 @@ namespace Avalonia.Diagnostics.ViewModels internal class ControlDetailsViewModel : ViewModelBase, IDisposable { private readonly IVisual _control; - private readonly IDictionary> _propertyIndex; + private IDictionary> _propertyIndex; private PropertyViewModel? _selectedProperty; + private DataGridCollectionView _propertiesView; private bool _snapshotStyles; private bool _showInactiveStyles; private string? _styleStatus; + private object _selectedEntity; + private readonly Stack> _selectedEntitiesStack = new(); + private string _selectedEntityName; + private string _selectedEntityType; public ControlDetailsViewModel(TreePageViewModel treePage, IVisual control) { _control = control; TreePage = treePage; - - var properties = GetAvaloniaProperties(control) - .Concat(GetClrProperties(control)) - .OrderBy(x => x, PropertyComparer.Instance) - .ThenBy(x => x.Name) - .ToList(); - - _propertyIndex = properties.GroupBy(x => x.Key).ToDictionary(x => x.Key, x => x.ToList()); - - var view = new DataGridCollectionView(properties); - view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.Group))); - view.Filter = FilterProperty; - PropertiesView = view; - + Layout = new ControlLayoutViewModel(control); - if (control is INotifyPropertyChanged inpc) - { - inpc.PropertyChanged += ControlPropertyChanged; - } - - if (control is AvaloniaObject ao) - { - ao.PropertyChanged += ControlPropertyChanged; - } + NavigateToProperty(control, (control as IControl)?.Name ?? control.ToString()); AppliedStyles = new ObservableCollection(); PseudoClasses = new ObservableCollection(); @@ -133,12 +117,46 @@ namespace Avalonia.Diagnostics.ViewModels public TreePageViewModel TreePage { get; } - public DataGridCollectionView PropertiesView { get; } + public DataGridCollectionView PropertiesView + { + get => _propertiesView; + private set => RaiseAndSetIfChanged(ref _propertiesView, value); + } public ObservableCollection AppliedStyles { get; } public ObservableCollection PseudoClasses { get; } + public object SelectedEntity + { + get => _selectedEntity; + set + { + RaiseAndSetIfChanged(ref _selectedEntity, value); + + } + } + + public string SelectedEntityName + { + get => _selectedEntityName; + set + { + RaiseAndSetIfChanged(ref _selectedEntityName, value); + + } + } + + public string SelectedEntityType + { + get => _selectedEntityType; + set + { + RaiseAndSetIfChanged(ref _selectedEntityType, value); + + } + } + public PropertyViewModel? SelectedProperty { get => _selectedProperty; @@ -378,5 +396,69 @@ namespace Avalonia.Diagnostics.ViewModels } } } + + public void ApplySelectedProperty() + { + if (SelectedProperty == null) return; + + var property = (_selectedEntity as IControl)?.GetValue(SelectedProperty.Key as AvaloniaProperty); + if (property == null) + { + property = _selectedEntity.GetType().GetProperty(SelectedProperty.Name)?.GetValue(_selectedEntity); + } + + if (property == null) return; + _selectedEntitiesStack.Push(new Tuple(SelectedEntityName, SelectedEntity)); + NavigateToProperty(property, SelectedProperty.Name); + } + + public void ApplyParentProperty() + { + if (_selectedEntitiesStack.Any()) + { + var property = _selectedEntitiesStack.Pop(); + NavigateToProperty(property.Item2, property.Item1); + } + } + + protected void NavigateToProperty(object o, string entityName) + { + if (SelectedEntity is INotifyPropertyChanged inpc1) + { + inpc1.PropertyChanged -= ControlPropertyChanged; + } + + if (SelectedEntity is AvaloniaObject ao1) + { + ao1.PropertyChanged -= ControlPropertyChanged; + } + + SelectedEntity = o; + SelectedEntityName = entityName; + SelectedEntityType = o.ToString(); + var properties = GetAvaloniaProperties(o) + .Concat(GetClrProperties(o)) + .OrderBy(x => x, PropertyComparer.Instance) + .ThenBy(x => x.Name) + .ToList(); + + _propertyIndex = properties.GroupBy(x => x.Key).ToDictionary(x => x.Key, x => x.ToList()); + + var view = new DataGridCollectionView(properties); + view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.Group))); + view.Filter = FilterProperty; + PropertiesView = view; + + if (o is INotifyPropertyChanged inpc2) + { + inpc2.PropertyChanged += ControlPropertyChanged; + } + + if (o is AvaloniaObject ao2) + { + ao2.PropertyChanged += ControlPropertyChanged; + } + + } } } diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml index 4b37438993..0d81127c21 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml @@ -13,23 +13,30 @@ - + - +