# Trees

It's very easy to add custom tree's, you can use the BaseTree component and extend from there. Our own trees, like the Content Tree and Media Tree do exactly this.

This is the Content Tree using the BaseTree, most of the methods are self explanatory by their name

```csharp
<BaseTree
    T="Content"
    Data="@Data"
    TreeAlias="@Constants.Sections.Trees.ContentTree"
    Expand="@OnExpandHandler"
    Change="@OnChangeHandler"
    @bind-Value="@Value"
    HasChildren="@(e => HasChildren(e))"
    DisableContextMenu="DisableContextMenu"
    DisableSectionOnlyContextMenu="DisableSectionOnlyContextMenu"
    ShouldBeExpanded="@(e => ShouldBeExpanded(e))"
    Template="@(TreeExtensions.CreateContentTreeTemplate<object>())">
</BaseTree>
```

If you want to view the entire component then you can view it on Github below

[https://github.com/YodasMyDad/ZauberCMS/blob/main-mvc/ZauberCMS.Components/Admin/Trees/ContentTree.razor](https://github.com/YodasMyDad/ZauberCMS/blob/main-mvc/ZauberCMS.Components/Admin/Trees/ContentTree.razor)

### Reusing Content & Media Trees

You can reuse the built in content and media tree's in your own plugins / extensions. You can either embed the tree within your component - Just like we do in the Content Picker component. This is using the Tree within your own component

```csharp
<ContentTree ValueChanged="OnValueChangedHandler"/>    
```

Making sure you pass in a method you want called when the content is selected

```csharp
private void OnValueChangedHandler(object value)
{
    if (value is Content)
    {
        // Do whatever you want
    }
}
```

### Opening Tree's In Dialogs

If you want to open the ContentTree or Media in a Dialog to just get the selected content, you can do it like so.

Make sure you pass in the IModalService in your component using the CascadingParameter

```csharp
[CascadingParameter] public IModalService? ModalService { get; set; }
```

Then create your method to call the ContentTree in a side dialog, notice that you pass in your method as a callback.

```csharp
private void AddContent()
{
    var parameters = new Dictionary<string, object>
    {
        { nameof(ContentTree.ValueChanged), EventCallback.Factory.Create<object>(this, OnValueChangedHandler) },
        { nameof(ContentTree.DisableContextMenu), true }
    };

    Modal = ModalService?.OpenSidePanel<ContentTree>("Choose Content", parameters);
}
```

The method to capture the selected item

```csharp
private async Task OnValueChangedHandler(object value)
{
    if (value is Content content)
    {
        // Do what you want
    }
}
```

### Pickers

If you are just looking for the ability to pick some content or media in your components, then it would be better to just reuse the Content Picker or Media Picker that we use internally.

You can reuse them just as easily, where Value is the property you want to bind the selected value to:

```csharp
<ContentPickerProperty
    Value="@MyStringId"
    Settings="@(JsonSerializer.Serialize(new ContentPickerSettings { MaxAllowed = 1 }))"
    ValueChanged="@(e => MyStringId = e.ToString())"/>
```

Pickers allow certain settings, and you can pass the settings as a serialized string. Exactly the same applies to the media picker

```csharp
<MediaPickerProperty
    Value="@ContentType.MediaIdAsString"
    Settings="@(JsonSerializer.Serialize(new MediaPickerSettings { MaxAllowed = 1 }))"
    ValueChanged="@(e => ContentType.MediaIdAsString = e.ToString())"/>
```
