Search code examples
c#wpftreeviewtreeviewitem

How to delete dynamically created tree view items


I have a WPF application that allows the user to dynamically create sub-items in a treeview. These sub-items are created from a separate window, and added to the main window. I would also like to implement a delete method that would be deleting main window sub-items from a separate window.

These are my thoughts along with some code:

//Okay button -- Delete sub-items in main window TreeView
private void button2_Click(object sender, RoutedEventArgs e)
{
    //Query for Window1
    var mainWindow = Application.Current.Windows
        .Cast<Window1>()
        .FirstOrDefault(window => window is Window1) as Window1;

    //Name of header that needs to be located
    string header = textBox1.Text;

    //While treeview from main window contains subitems
    while (!mainWindow.treeView.Items.IsEmpty)
    {
        //Find TreeView subitem with matching header
        //? - not sure on code

        //Delete TreeView subitem
        //I'm guessing it has something to do with
        //mainWindow.treeView.Items.Remove(At?)....
    }
}

My comments show what I'm unsure about. I've correctly queried my mainWindow, and set a string value for the header that I want to find. I've set up a loop to search through my treeview, but don't know the exact code to get the job done. Please show me the code that I should be using.

Revised code based on answer

I'm doing my best to understand your answer. I've explained what I'm trying to do in my comments. I think I'm on the right track, but run into a little compiler error when I try to use RemoveAll. Do I need to include some kind of a using resourceDictionary?

Code Revision

Thanks a lot for sticking with me. The compiler is still giving errors for the call to RemoveAll.

//Okay button -- Delete location and corrusponding block
    private void button2_Click(object sender, RoutedEventArgs e)
    {
        //Close Delete Window
        this.Close();

        //Query for Window1
        var mainWindow = Application.Current.Windows
            .Cast<Window1>()
            .FirstOrDefault(window => window is Window1) as Window1;

        //Name of header that needs to be located
        string header = textBox1.Text;

        //Treeview under operation from main window
        TreeViewItem items = mainWindow.treeViewItem;

        //Delete corresponding node
        RemoveAll(items, p => string.Equals(p.Header, header));
    }

    //REMOVE ALL METHOD - for use with button_click ^
    public void RemoveAll(ItemCollection items, Predicate<TreeViewItem> isValid)
    {
        for (int i = items.Count - 1; i >= 0; i--)
        {
            TreeViewItem vItem = (TreeViewItem)items[i];
            if (isValid(vItem))
            {
                items.RemoveAt(i);
            }
            else
            {
                RemoveAll(vItem.Items, isValid);
            }
        }
    }

Buld Errors

ERROR 1: The best overloaded method match for '...(project)...' has some invalid arguments.

ERROR 2: Argument '1': cannot convert from System.Windows.Controls.TreeViewitem to `System.Windows.Controls.ItemCollection'.

Thank you.


Solution

  • public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            string header = txtRemove.Text; //name of Treeviewitem to delete
            TreeView view = trvView; //get from location
    
            RemoveAll(view.Items, p => string.Equals(p.Header, header));
        }
    
        public bool Remove(ItemCollection items, Predicate<TreeViewItem> isValid)
        {
            for (int i = items.Count - 1; i >= 0; i--)
            {
                TreeViewItem vItem = (TreeViewItem)items[i];
                if (isValid(vItem))
                {
                    items.RemoveAt(i);
                    return true;
                }
                else
                {
                    bool isDeleted = Remove(vItem.Items, isValid);
                    if (isDeleted)
                        return isDeleted;
                }
            }
            return false;
        }
    
        public void RemoveAll(ItemCollection items, Predicate<TreeViewItem> isValid)
        {
            for (int i = items.Count - 1; i >= 0; i--)
            {
                TreeViewItem vItem = (TreeViewItem)items[i];
                if (isValid(vItem))
                {
                    items.RemoveAt(i);
                }
                else
                {
                    RemoveAll(vItem.Items, isValid);
                }
            }
        }
    
    }
    

    ///Xaml

    <Window x:Class="TreeViewSample.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <TreeView x:Name="trvView" HorizontalAlignment="Left" Height="215" Margin="68,35,0,0" VerticalAlignment="Top" Width="221">
                <TreeView.Items>
                    <TreeViewItem Header="1">
                        <TreeViewItem Header="1/1"/>
                        <TreeViewItem Header="1/2"/>
                        <TreeViewItem Header="1/3"/>
                    </TreeViewItem>
                    <TreeViewItem Header="2">
                        <TreeViewItem Header="2/1"/>
                        <TreeViewItem Header="2/2"/>
                        <TreeViewItem Header="2/3"/>
                    </TreeViewItem>
                    <TreeViewItem Header="3">
                        <TreeViewItem Header="3/1"/>
                        <TreeViewItem Header="3/2"/>
                        <TreeViewItem Header="3/3"/>
                    </TreeViewItem>
                </TreeView.Items>
    
            </TreeView>
            <Button  Content="Button" HorizontalAlignment="Left" Margin="333,155,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
            <TextBox x:Name="txtRemove" HorizontalAlignment="Left" Height="23" Margin="333,102,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
    
        </Grid>
    </Window>