This is a migrated thread and some comments may be shown as answers.

Bind Style based on Selected Node

5 Answers 303 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Joel
Top achievements
Rank 2
Iron
Iron
Iron
Joel asked on 12 Mar 2020, 04:30 PM

For this TreeView definition, I want the button background to be black with white font when the TreeItem.Selected property is true.  Then, I want the node to go back to a clear background with black font when when that property is false.  How do I do this?

 

@using System.Collections.ObjectModel
@using Palmer.Doc.Models
 
@page "/tree"
 
 
<TelerikButton Primary="true" OnClick="CreateItem">Create item</TelerikButton>
 
<TelerikButton Primary="true" OnClick="DeleteItem">Delete item</TelerikButton>
 
<TelerikTreeView Data="@TreeData">
    <TreeViewBindings>
        <TreeViewBinding IdField="Id"
                         TextField="Text">
            <ItemTemplate>
                @{
                    <TelerikButton OnClick="@(() => OnClickHandler(context as TreeItem))">@((context as TreeItem).Text)</TelerikButton>
                }
            </ItemTemplate>
        </TreeViewBinding>
    </TreeViewBindings>
</TelerikTreeView>
 
@code{
 
    public class TreeItem
    {
        public string Id { get; set; } = $"{Guid.NewGuid()}";
        public string Text { get; set; }
        public string ContextId { get; set; }
        public ObservableCollection<TreeItem> Items { get; set; } = new ObservableCollection<TreeItem>();
        public bool Expanded { get; set; }
        public bool HasChildren { get; set; }
        public bool Selected { get; set; }
    }
 
    #region Properties
 
    public TreeItem SelectedItem { get; set; }
    public ObservableCollection<TreeItem> TreeData { get; set; }
 
    #endregion
 
    #region Event Handlers
 
    protected override void OnInitialized()
    {
        LoadHierarchical();
    }
 
    private void OnClickHandler(TreeItem context)
    {
        SelectedItem = context;
    }
 
    #endregion
 
    #region Methods
 
    private void CreateItem()
    {
        if (SelectedItem != null)
        {
            AddNode(SelectedItem, "New Item");
        }
    }
 
    private void DeleteItem()
    {
        if (SelectedItem != null)
        {
            TreeItem parent = GetById(SelectedItem.ContextId);
            if (parent != null)
            {
                parent.Items.Remove(SelectedItem);
 
                SelectedItem = parent;
                SelectedItem.HasChildren = SelectedItem.Items.Count > 0;
                SelectedItem.Expanded = SelectedItem.HasChildren;
            }
        }
    }
 
    private void LoadHierarchical()
    {
        ObservableCollection<TreeItem> roots =
        new ObservableCollection<TreeItem>()
        {
            new TreeItem { Text = "Item 1", Expanded = true },
            new TreeItem { Text = "Item 2" }
            };
 
        AddNode(roots[0], "Item 1 first child");
        AddNode(roots[0], "Item 1 second child");
        AddNode(roots[1], "Item 2 first child");
        AddNode(roots[1], "Item 2 second child");
 
        TreeData = roots;
    }
 
    private void AddNode(TreeItem parent, string childText)
    {
        AddNode(parent, new TreeItem()
        {
            Text = childText
        });
    }
 
    private void AddNode(TreeItem context, TreeItem child)
    {
        child.ContextId = context.Id;
 
        context.Items.Add(child);
        context.HasChildren = true;
        context.Expanded = true;
 
        SelectedItem = child;
    }
 
    public TreeItem GetById(string id)
    {
        TreeItem result = null;
 
        // perform a recursive search starting with the root nodes
        foreach (var treeItem in TreeData)
        {
            result = getById(id, treeItem);
            if (result != null) break;
        }
 
        return result;
    }
 
    /// <summary>
    /// Perform a recursive search using the given node
    /// </summary>
    /// <param name="id"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    private TreeItem getById(string id, TreeItem node)
    {
        TreeItem result = null;
 
        if (node.Id == id)
        {
            result = node;
        }
        else
        {
            foreach (TreeItem child in node.Items)
            {
                result = getById(id, child);
                if (result != null) break;
            }
        }
 
        return result;
    }
 
    #endregion
}

5 Answers, 1 is accepted

Sort by
0
Svetoslav Dimitrov
Telerik team
answered on 13 Mar 2020, 10:08 AM

Hello Joel,

You can bind some styles on the selected node by following the instructions below:

  1. In the OnClickHandler method you need to toggle the Selected property between true and false
  2. Use conditional statement based on Selected inside the Class property of the TelerikButton
  3. Create the custom css style

To further demonstrate that I have build a demo which is as attached file.

To sum the demo up you can see the code snippet below:

<TelerikTreeView Data="@TreeData">
    <TreeViewBindings>
        <TreeViewBinding IdField="Id"
                         TextField="Text">
            <ItemTemplate>
                @{
                    TreeItem item = context as TreeItem;
                    <TelerikButton Class="@( item.Selected ? "selected-button" : "" )" 
                                   OnClick="@(() => OnClickHandler(item))">
                        @(item.Text)
                    </TelerikButton>
                }
            </ItemTemplate>
        </TreeViewBinding>
    </TreeViewBindings>
</TelerikTreeView>

@code {
    private void OnClickHandler(TreeItem context)
    {
        SelectedItem = context;
        context.Selected = !context.Selected;
    }
}

<style>
    .selected-button.k-button {
        background-color: black;
        background-image: none;
        color: white;
    }
</style>

Regards,
Svetoslav Dimitrov
Progress Telerik

 UI for Blazor
0
Joel
Top achievements
Rank 2
Iron
Iron
Iron
answered on 13 Mar 2020, 01:58 PM

Your example didn't compile because on the ItemTemplate the compiler doesn't know "item".  I updated the code and now it compiles but the style doesn't get applied.  Any ideas?  Also, I really need to learn more about styles.

<ItemTemplate>
    @{
        <TelerikButton Class="@( ((TreeItem)context).Selected ? "selected-button" : "" )"
                       OnClick="@(() => OnClickHandler(context as TreeItem))">@((context as TreeItem).Text)</TelerikButton>
    }
</ItemTemplate>
0
Svetoslav Dimitrov
Telerik team
answered on 13 Mar 2020, 03:45 PM

Hello Joel,

Could you please confirm that you have a definition of the item in your template like so:

<TelerikTreeView Data="@TreeData">
    <TreeViewBindings>
        <TreeViewBinding IdField="Id"
                         TextField="Text">
            <ItemTemplate>
                @{
                    TreeItem item = context as TreeItem;
                    <TelerikButton Class="@( item.Selected ? "selected-button" : "" )" 
                                   OnClick="@(() => OnClickHandler(item))">
                        @(item.Text)
                    </TelerikButton>
                }
            </ItemTemplate>
        </TreeViewBinding>
    </TreeViewBindings>
</TelerikTreeView>

In case you do, please follow up with the modified code you made so we can work on the same ground and investigate where the issue originates from.

Regards,
Svetoslav Dimitrov
Progress Telerik

 UI for Blazor
0
Joel
Top achievements
Rank 2
Iron
Iron
Iron
answered on 13 Mar 2020, 08:13 PM

Yes, you are correct.  That was silly of me to not catch the "item".  However, the style application continues to not work.  My test project continues to evolve.  My current definitions:

Tree.razor

@using System.Collections.ObjectModel
@using Palmer.Doc.Models
 
@page "/tree"
@inherits TreeBase
 
<div class="row">
    <div class="col-md-4">
        <TelerikButton Primary="true" OnClick="CreateItem">Create item</TelerikButton>
        <TelerikButton Primary="false" OnClick="DeleteItem">Delete item</TelerikButton>
 
        <br />
        <br />
 
        <TelerikTreeView Data="@TreeData">
            <TreeViewBindings>
                <TreeViewBinding IdField="Id"
                                 TextField="Text">
                    <ItemTemplate>
                        @{
                            TreeItem item = context as TreeItem;
                            <TelerikButton Class="@(item.Selected ? "selected-button" : "" )"
                                           OnClick="@(() => OnClickHandler(item))">@(item.Text)</TelerikButton>
                        }
                    </ItemTemplate>
                </TreeViewBinding>
            </TreeViewBindings>
        </TelerikTreeView>
    </div>
    <div class="col-md-8">
        <h7><b>Selected Item:</b></h7>
        <br />
        <h7>@SelectedItem.Path</h7>
 
        <br />
        <br />
        <h7><b>Node Name:</b></h7>
        <br />
        <TelerikTextBox @bind-Value="SelectedItem.Text" Width="100%" />
 
        <br />
        <br />
        <h7><b>Documentation:</b></h7>
        <br />
        <textarea rows="15" Width="100%" placeholder="...documentation" @bind=SelectedItem.Documentation></textarea>
    </div>
</div>
 
<style>
    .selected-button.k-button {
        background-color: black;
        background-image: none;
        color: white;
    }
</style>

 

TreeBase.cs:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Palmer.Doc.Models;
 
namespace Palmer.Doc.Pages
{
    public class TreeBase : ComponentBase
    {
        protected override Task OnInitializedAsync()
        {
            LoadHierarchical();
 
            return base.OnInitializedAsync();
        }
 
        #region Properties
 
        public TreeItem SelectedItem { get; set; }
        public ObservableCollection<TreeItem> TreeData { get; set; }
 
        #endregion
 
        #region Event Handlers
 
        protected override void OnInitialized()
        {
            LoadHierarchical();
        }
 
        public void OnClickHandler(TreeItem context)
        {
            SelectedItem = context;
 
            List<TreeItem> parents = GetHierarchy(SelectedItem);
 
            SelectedItem.Path = GetPath(parents);
        }
 
        #endregion
 
        #region Methods
 
        public void CreateItem()
        {
            if (SelectedItem != null)
            {
                AddNode(SelectedItem, "New Item");
            }
        }
 
        public void DeleteItem()
        {
            if (SelectedItem != null)
            {
                TreeItem parent = GetById(SelectedItem.ContextId);
                if (parent != null)
                {
                    parent.Items.Remove(SelectedItem);
 
                    SelectedItem = parent;
                    SelectedItem.HasChildren = SelectedItem.Items.Count > 0;
                    SelectedItem.Expanded = SelectedItem.HasChildren;
                }
            }
        }
 
        private void LoadHierarchical()
        {
            ObservableCollection<TreeItem> roots =
                new ObservableCollection<TreeItem>()
                {
                    new TreeItem {Text = "Item 1", Expanded = true},
                    new TreeItem {Text = "Item 2"}
                };
 
            AddNode(roots[0], "First child");
            AddNode(roots[0], "Second child");
            AddNode(roots[1], "First child");
            AddNode(roots[1], "Second child");
 
            TreeData = roots;
            SelectedItem = roots[0];
        }
 
        private void AddNode(TreeItem parent, string childText)
        {
            AddNode(parent, new TreeItem()
            {
                Text = childText
            });
        }
 
        private void AddNode(TreeItem context, TreeItem child)
        {
            child.ContextId = context.Id;
 
            context.Items.Add(child);
            context.HasChildren = true;
            context.Expanded = true;
 
            SelectedItem = child;
        }
 
        public string GetPath(List<TreeItem> parents)
        {
            string result = "";
 
            foreach (TreeItem item in parents)
            {
                result = $"{item.Text} > {result}";
            }
 
            return result.Substring(0, result.Length - 2).Trim();
        }
 
        public List<TreeItem> GetHierarchy(TreeItem node)
        {
            List<TreeItem> result = new List<TreeItem>();
            result.Add(node);
 
            if (node.ContextId != null)
            {
                TreeItem parent = GetById(node.ContextId);
                result.AddRange(GetHierarchy(parent));
            }
 
            return result;
        }
 
        public TreeItem GetById(string id)
        {
            TreeItem result = null;
 
            // perform a recursive search starting with the root nodes
            foreach (var treeItem in TreeData)
            {
                result = getById(id, treeItem);
                if (result != null) break;
            }
 
            return result;
        }
 
        /// <summary>
        /// Perform a recursive search using the given node
        /// </summary>
        /// <param name="id"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        private TreeItem getById(string id, TreeItem node)
        {
            TreeItem result = null;
 
            if (node.Id == id)
            {
                result = node;
            }
            else
            {
                foreach (TreeItem child in node.Items)
                {
                    result = getById(id, child);
                    if (result != null) break;
                }
            }
 
            return result;
        }
 
        #endregion
    }
}

 

 

0
Accepted
Svetoslav Dimitrov
Telerik team
answered on 16 Mar 2020, 02:43 PM

Hello Joel,

In order to change the styles you need add this line to your OnClickHandler method:

context.Selected = !context.Selected;

If that line is missing you will not be able to apply the CSS class that changes the style.

That behavior can be observed by Inspecting (F12) the button in the browser.

Regards,
Svetoslav Dimitrov
Progress Telerik

 UI for Blazor
Tags
TreeView
Asked by
Joel
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Svetoslav Dimitrov
Telerik team
Joel
Top achievements
Rank 2
Iron
Iron
Iron
Share this question
or