diff --git a/BlazingDev.BlazorToolkit/Components/BzObjectInspector.razor b/BlazingDev.BlazorToolkit/Components/BzObjectInspector.razor new file mode 100644 index 0000000..9dbd522 --- /dev/null +++ b/BlazingDev.BlazorToolkit/Components/BzObjectInspector.razor @@ -0,0 +1,59 @@ +@page "/BzObjectInspector" +@using System.Reflection + +
+ @RenderObjectTree(ObjectToInspect) +
+ +@code { + [Parameter] public object ObjectToInspect { get; set; } + + private RenderFragment RenderObjectTree(object obj) => builder => + { + var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); + foreach (var property in properties) + { + var value = property.GetValue(obj); + var isExpandable = value != null && !value.GetType().IsPrimitive && value.GetType() != typeof(string); + + builder.OpenElement(0, "div"); + builder.AddAttribute(1, "class", "bz-object-inspector-node"); + + if (isExpandable) + { + builder.OpenElement(2, "button"); + builder.AddAttribute(3, "onclick", EventCallback.Factory.Create(this, () => ToggleExpandCollapse(property.Name))); + builder.AddContent(4, IsExpanded(property.Name) ? "-" : "+"); + builder.CloseElement(); + } + + builder.AddContent(5, $"{property.Name}: {value}"); + + if (isExpandable && IsExpanded(property.Name)) + { + builder.OpenElement(6, "div"); + builder.AddAttribute(7, "class", "bz-object-inspector-children"); + builder.AddContent(8, RenderObjectTree(value)); + builder.CloseElement(); + } + + builder.CloseElement(); + } + }; + + private HashSet expandedNodes = new(); + + private void ToggleExpandCollapse(string nodeName) + { + if (expandedNodes.Contains(nodeName)) + { + expandedNodes.Remove(nodeName); + } + else + { + expandedNodes.Add(nodeName); + } + } + + private bool IsExpanded(string nodeName) => expandedNodes.Contains(nodeName); +} diff --git a/BlazingDev.BlazorToolkit/Components/BzObjectInspector.razor.cs b/BlazingDev.BlazorToolkit/Components/BzObjectInspector.razor.cs new file mode 100644 index 0000000..336c520 --- /dev/null +++ b/BlazingDev.BlazorToolkit/Components/BzObjectInspector.razor.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Components; +using System.Reflection; + +namespace BlazingDev.BlazorToolkit.Components; + +public partial class BzObjectInspector : ComponentBase +{ + [Parameter] public object ObjectToInspect { get; set; } + + private HashSet expandedNodes = new(); + + private RenderFragment RenderObjectTree(object obj) => builder => + { + var properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); + foreach (var property in properties) + { + var value = property.GetValue(obj); + var isExpandable = value != null && !value.GetType().IsPrimitive && value.GetType() != typeof(string); + + builder.OpenElement(0, "div"); + builder.AddAttribute(1, "class", "bz-object-inspector-node"); + + if (isExpandable) + { + builder.OpenElement(2, "button"); + builder.AddAttribute(3, "onclick", EventCallback.Factory.Create(this, () => ToggleExpandCollapse(property.Name))); + builder.AddContent(4, IsExpanded(property.Name) ? "-" : "+"); + builder.CloseElement(); + } + + builder.AddContent(5, $"{property.Name}: {value}"); + + if (isExpandable && IsExpanded(property.Name)) + { + builder.OpenElement(6, "div"); + builder.AddAttribute(7, "class", "bz-object-inspector-children"); + builder.AddContent(8, RenderObjectTree(value)); + builder.CloseElement(); + } + + builder.CloseElement(); + } + }; + + private void ToggleExpandCollapse(string nodeName) + { + if (expandedNodes.Contains(nodeName)) + { + expandedNodes.Remove(nodeName); + } + else + { + expandedNodes.Add(nodeName); + } + } + + private bool IsExpanded(string nodeName) => expandedNodes.Contains(nodeName); +} diff --git a/Playground/AppFrame/NavMenu.razor b/Playground/AppFrame/NavMenu.razor index 520459e..68b89ee 100644 --- a/Playground/AppFrame/NavMenu.razor +++ b/Playground/AppFrame/NavMenu.razor @@ -19,5 +19,11 @@ BzTimerComponents + + diff --git a/Playground/Components/BzObjectInspectorUsage.razor b/Playground/Components/BzObjectInspectorUsage.razor new file mode 100644 index 0000000..b41735c --- /dev/null +++ b/Playground/Components/BzObjectInspectorUsage.razor @@ -0,0 +1,37 @@ +@page "/BzObjectInspectorUsage" +@using BlazingDev.BlazorToolkit.Components + + +

Object Inspector Usage

+ +
+ +@code { + private SampleObject sampleObject = new SampleObject + { + Name = "Sample Object", + Age = 30, + Address = new Address + { + Street = "123 Main St", + City = "Anytown", + State = "CA", + ZipCode = "12345" + } + }; + + private class SampleObject + { + public string Name { get; set; } + public int Age { get; set; } + public Address Address { get; set; } + } + + private class Address + { + public string Street { get; set; } + public string City { get; set; } + public string State { get; set; } + public string ZipCode { get; set; } + } +} diff --git a/Playground/Pages/BzObjectInspectorPage.razor b/Playground/Pages/BzObjectInspectorPage.razor new file mode 100644 index 0000000..3ff7fef --- /dev/null +++ b/Playground/Pages/BzObjectInspectorPage.razor @@ -0,0 +1,9 @@ +@page "/BzObjectInspector" + +BzObjectInspector + +

BzObjectInspector

+ +

This page showcases the BzObjectInspector component in the Playground app.

+ +