diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs index c8f618580b..b4243c6088 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlDetailsViewModel.cs @@ -132,8 +132,7 @@ namespace Avalonia.Diagnostics.ViewModels { if (TreePage.UseRegexFilter) { - var regex = new Regex(TreePage.PropertyFilter); - return regex.IsMatch(property.Name); + return TreePage.FilterRegex?.IsMatch(property.Name) ?? true; } return property.Name.IndexOf(TreePage.PropertyFilter, StringComparison.OrdinalIgnoreCase) != -1; diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs index 77594570ed..da2fd25c0c 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreePageViewModel.cs @@ -1,11 +1,16 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text.RegularExpressions; using Avalonia.Controls; using Avalonia.VisualTree; namespace Avalonia.Diagnostics.ViewModels { - internal class TreePageViewModel : ViewModelBase, IDisposable + internal class TreePageViewModel : ViewModelBase, IDisposable, INotifyDataErrorInfo { + private readonly Dictionary _errors = new Dictionary(); private TreeNode _selectedNode; private ControlDetailsViewModel _details; private string _propertyFilter = string.Empty; @@ -14,17 +19,13 @@ namespace Avalonia.Diagnostics.ViewModels public TreePageViewModel(TreeNode[] nodes) { Nodes = nodes; - Selection = new SelectionModel - { - SingleSelect = true, - Source = Nodes - }; + Selection = new SelectionModel { SingleSelect = true, Source = Nodes }; Selection.SelectionChanged += (s, e) => { SelectedNode = (TreeNode)Selection.SelectedItem; }; - } + } public TreeNode[] Nodes { get; protected set; } @@ -58,6 +59,37 @@ namespace Avalonia.Diagnostics.ViewModels } } + public Regex FilterRegex { get; set; } + + private void UpdateFilterRegex() + { + void ClearError() + { + if (_errors.Remove(nameof(PropertyFilter))) + { + ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(PropertyFilter))); + } + } + + if (UseRegexFilter) + { + try + { + FilterRegex = new Regex(PropertyFilter); + ClearError(); + } + catch (Exception exception) + { + _errors[nameof(PropertyFilter)] = exception.Message; + ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(PropertyFilter))); + } + } + else + { + ClearError(); + } + } + public string PropertyFilter { get => _propertyFilter; @@ -65,6 +97,7 @@ namespace Avalonia.Diagnostics.ViewModels { if (RaiseAndSetIfChanged(ref _propertyFilter, value)) { + UpdateFilterRegex(); Details.PropertiesView.Refresh(); } } @@ -77,6 +110,7 @@ namespace Avalonia.Diagnostics.ViewModels { if (RaiseAndSetIfChanged(ref _useRegexFilter, value)) { + UpdateFilterRegex(); Details.PropertiesView.Refresh(); } } @@ -158,5 +192,17 @@ namespace Avalonia.Diagnostics.ViewModels return null; } + + public IEnumerable GetErrors(string propertyName) + { + if (_errors.TryGetValue(propertyName, out var error)) + { + yield return error; + } + } + + public bool HasErrors => _errors.Count > 0; + + public event EventHandler ErrorsChanged; } }