Skip to content

Commit 475d8b7

Browse files
Takoooooodanwalmsley
authored andcommitted
Merge pull request #6790 from ltetak/devtools_dc_navigate
DevTools - allow to navigate to children (especially DataContext)
1 parent 6749bae commit 475d8b7

File tree

3 files changed

+130
-30
lines changed

3 files changed

+130
-30
lines changed

src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,26 @@ namespace Avalonia.Diagnostics.ViewModels
1717
internal class ControlDetailsViewModel : ViewModelBase, IDisposable
1818
{
1919
private readonly IVisual _control;
20-
private readonly IDictionary<object, List<PropertyViewModel>> _propertyIndex;
20+
private IDictionary<object, List<PropertyViewModel>> _propertyIndex;
2121
private PropertyViewModel? _selectedProperty;
22+
private DataGridCollectionView _propertiesView;
2223
private bool _snapshotStyles;
2324
private bool _showInactiveStyles;
2425
private string? _styleStatus;
26+
private object _selectedEntity;
27+
private readonly Stack<Tuple<string, object>> _selectedEntitiesStack = new Stack<Tuple<string, object>>();
28+
private string _selectedEntityName;
29+
private string _selectedEntityType;
2530

2631
public ControlDetailsViewModel(TreePageViewModel treePage, IVisual control)
2732
{
2833
_control = control;
2934

3035
TreePage = treePage;
31-
32-
var properties = GetAvaloniaProperties(control)
33-
.Concat(GetClrProperties(control))
34-
.OrderBy(x => x, PropertyComparer.Instance)
35-
.ThenBy(x => x.Name)
36-
.ToList();
37-
38-
_propertyIndex = properties.GroupBy(x => x.Key).ToDictionary(x => x.Key, x => x.ToList());
39-
40-
var view = new DataGridCollectionView(properties);
41-
view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.Group)));
42-
view.Filter = FilterProperty;
43-
PropertiesView = view;
44-
36+
4537
Layout = new ControlLayoutViewModel(control);
4638

47-
if (control is INotifyPropertyChanged inpc)
48-
{
49-
inpc.PropertyChanged += ControlPropertyChanged;
50-
}
51-
52-
if (control is AvaloniaObject ao)
53-
{
54-
ao.PropertyChanged += ControlPropertyChanged;
55-
}
39+
NavigateToProperty(control, (control as IControl)?.Name ?? control.ToString());
5640

5741
AppliedStyles = new ObservableCollection<StyleViewModel>();
5842
PseudoClasses = new ObservableCollection<PseudoClassViewModel>();
@@ -133,12 +117,46 @@ public ControlDetailsViewModel(TreePageViewModel treePage, IVisual control)
133117

134118
public TreePageViewModel TreePage { get; }
135119

136-
public DataGridCollectionView PropertiesView { get; }
120+
public DataGridCollectionView PropertiesView
121+
{
122+
get => _propertiesView;
123+
private set => RaiseAndSetIfChanged(ref _propertiesView, value);
124+
}
137125

138126
public ObservableCollection<StyleViewModel> AppliedStyles { get; }
139127

140128
public ObservableCollection<PseudoClassViewModel> PseudoClasses { get; }
141129

130+
public object SelectedEntity
131+
{
132+
get => _selectedEntity;
133+
set
134+
{
135+
RaiseAndSetIfChanged(ref _selectedEntity, value);
136+
137+
}
138+
}
139+
140+
public string SelectedEntityName
141+
{
142+
get => _selectedEntityName;
143+
set
144+
{
145+
RaiseAndSetIfChanged(ref _selectedEntityName, value);
146+
147+
}
148+
}
149+
150+
public string SelectedEntityType
151+
{
152+
get => _selectedEntityType;
153+
set
154+
{
155+
RaiseAndSetIfChanged(ref _selectedEntityType, value);
156+
157+
}
158+
}
159+
142160
public PropertyViewModel? SelectedProperty
143161
{
144162
get => _selectedProperty;
@@ -378,5 +396,69 @@ private int GroupIndex(string? group)
378396
}
379397
}
380398
}
399+
400+
public void ApplySelectedProperty()
401+
{
402+
if (SelectedProperty == null) return;
403+
404+
var property = (_selectedEntity as IControl)?.GetValue(SelectedProperty.Key as AvaloniaProperty);
405+
if (property == null)
406+
{
407+
property = _selectedEntity.GetType().GetProperty(SelectedProperty.Name)?.GetValue(_selectedEntity);
408+
}
409+
410+
if (property == null) return;
411+
_selectedEntitiesStack.Push(new Tuple<string, object>(SelectedEntityName, SelectedEntity));
412+
NavigateToProperty(property, SelectedProperty.Name);
413+
}
414+
415+
public void ApplyParentProperty()
416+
{
417+
if (_selectedEntitiesStack.Any())
418+
{
419+
var property = _selectedEntitiesStack.Pop();
420+
NavigateToProperty(property.Item2, property.Item1);
421+
}
422+
}
423+
424+
protected void NavigateToProperty(object o, string entityName)
425+
{
426+
if (SelectedEntity is INotifyPropertyChanged inpc1)
427+
{
428+
inpc1.PropertyChanged -= ControlPropertyChanged;
429+
}
430+
431+
if (SelectedEntity is AvaloniaObject ao1)
432+
{
433+
ao1.PropertyChanged -= ControlPropertyChanged;
434+
}
435+
436+
SelectedEntity = o;
437+
SelectedEntityName = entityName;
438+
SelectedEntityType = o.ToString();
439+
var properties = GetAvaloniaProperties(o)
440+
.Concat(GetClrProperties(o))
441+
.OrderBy(x => x, PropertyComparer.Instance)
442+
.ThenBy(x => x.Name)
443+
.ToList();
444+
445+
_propertyIndex = properties.GroupBy(x => x.Key).ToDictionary(x => x.Key, x => x.ToList());
446+
447+
var view = new DataGridCollectionView(properties);
448+
view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.Group)));
449+
view.Filter = FilterProperty;
450+
PropertiesView = view;
451+
452+
if (o is INotifyPropertyChanged inpc2)
453+
{
454+
inpc2.PropertyChanged += ControlPropertyChanged;
455+
}
456+
457+
if (o is AvaloniaObject ao2)
458+
{
459+
ao2.PropertyChanged += ControlPropertyChanged;
460+
}
461+
462+
}
381463
}
382464
}

src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,30 @@
1313

1414
<Grid ColumnDefinitions="*,Auto,320">
1515

16-
<Grid Grid.Column="0" RowDefinitions="Auto,*">
16+
<Grid Grid.Column="0" RowDefinitions="Auto,Auto,*">
1717

18-
<controls:FilterTextBox Grid.Row="0"
18+
<Grid ColumnDefinitions="Auto, *" RowDefinitions="Auto, Auto">
19+
<Button Grid.Column="0" Grid.RowSpan="2" Content="^" Command="{Binding ApplyParentProperty}" />
20+
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding SelectedEntityName}" FontWeight="Bold" />
21+
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding SelectedEntityType}" FontStyle="Italic" />
22+
</Grid>
23+
24+
<controls:FilterTextBox Grid.Row="1"
1925
BorderThickness="0"
2026
DataContext="{Binding TreePage.PropertiesFilter}"
2127
Text="{Binding FilterString}"
2228
Watermark="Filter properties"
2329
UseCaseSensitiveFilter="{Binding UseCaseSensitiveFilter}"
2430
UseWholeWordFilter="{Binding UseWholeWordFilter}"
25-
UseRegexFilter="{Binding UseRegexFilter}" />
31+
UseRegexFilter="{Binding UseRegexFilter}"/>
2632

2733
<DataGrid Items="{Binding PropertiesView}"
28-
Grid.Row="1"
34+
Grid.Row="2"
2935
BorderThickness="0"
3036
RowBackground="Transparent"
3137
SelectedItem="{Binding SelectedProperty, Mode=TwoWay}"
32-
CanUserResizeColumns="true">
38+
CanUserResizeColumns="true"
39+
DoubleTapped="PropertiesGrid_OnDoubleTapped">
3340
<DataGrid.Columns>
3441
<DataGridTextColumn Header="Property" Binding="{Binding Name}" IsReadOnly="True" />
3542
<DataGridTextColumn Header="Value" Binding="{Binding Value}" />

src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Avalonia.Controls;
2+
using Avalonia.Diagnostics.ViewModels;
3+
using Avalonia.Input;
24
using Avalonia.Markup.Xaml;
35

46
namespace Avalonia.Diagnostics.Views
@@ -14,5 +16,14 @@ private void InitializeComponent()
1416
{
1517
AvaloniaXamlLoader.Load(this);
1618
}
19+
20+
private void PropertiesGrid_OnDoubleTapped(object sender, TappedEventArgs e)
21+
{
22+
if (sender is DataGrid grid && grid.DataContext is ControlDetailsViewModel controlDetails)
23+
{
24+
controlDetails.ApplySelectedProperty();
25+
}
26+
27+
}
1728
}
1829
}

0 commit comments

Comments
 (0)