Shawn Darichuk
Shawn Darichuk

Reputation: 390

Checking if treeview contains an item

This problem seems simple enough. I have a treeview, let's call it MyTreeView, populated with all of the drive letters, so the treeview looks like this:
A:\
C:\
D:\
F:\

How do I check if the treeview contains a specific item? How does the treeview identify its items? I have created a MessageBox to show MyTreeView.Items.GetItemAt(1), and it identifies item 1 as:
"System.Windows.Controls.TreeViewItem Header:C:\ Items.Count:1"

Try the easiest thing first, which obviously doesn't work:

if (MyTreeView.Items.Contains(@"C:\")
{
    MessageBox.Show(@"Tree contains C:\");
}

The next easiest thing would be to try making a TreeViewItem that looks similar to what I want, which also doesn't work:

TreeViewItem myItem = new TreeViewItem();
myItem.Header = @"C:\";
if (MyTreeView.Items.Contains(myItem)
{
    MessageBox.Show("Tree contains " + myItem.ToString());
}

Just to make sure I had the fundamental concept right, I tried some circular logic, which actually does work:

var myItem = MyTreeView.Items.GetItemAt(1);
if (MyTreeView.Items.Contains(myItem)
{
    MessageBox.Show("Tree contains " + myItem.ToString());
}

Which outputs:
"Tree contains System.Windows.Controls.TreeViewItem Header:C:\ Items.Count:1"

What am I doing wrong? How do I check if my tree contains something like "C:\" ?

edit:
The code for building the tree is this:
(basically a copy and paste from the internet)

        foreach (string myString in Directory.GetLogicalDrives())
        {
            TreeViewItem item = new TreeViewItem();
            item.Header = myString;
            item.Tag = myString;
            item.FontWeight = FontWeights.Normal;
            item.Items.Add(dummyNode); // this is (object)dummyNode = null
            item.Expanded += new RoutedEventHandler(DWGFolder_Expanded);
            item.Selected += new RoutedEventHandler(DWGFolder_Selected);
            // the Expanded event is very similar, 
            // subitem.Header is the folder name (Testing),
            // while subitem.Tag is the full path (C:\Testing)
            MyTreeView.Items.Add(item);
        }

So basically I'm trying to match TreeViewItem objects.

Upvotes: 1

Views: 3495

Answers (2)

almulo
almulo

Reputation: 4978

Contains looks for the exact same instance inside the collection. If you don't have the object you want to check already, you can't use Contains.

But you can use some basic LINQ query... Add the LINQ namespace to your class:

using System.Linq;

If your items are indeed just Strings, then use this query (EDIT - Though, in case they're just Strings, Contains should work, since their equality comparers don't behave like those of regular reference types, but compare by value):

if (MyTreeView.Items.Cast<string>().Any(s => s == @"C:\"))
{
    // Do stuff
}

If your items are TreeViewItems, you can use this one:

if (MyTreeView.Items.Cast<TreeViewItem>().Any(i => i.Header.ToString() == @"C:\"))
{
    // Do stuff
}

But your items could be any class we don't know, or your header binding could change... Without knowing how you're adding the items to the TreeView, it's hard to give you the best alternative.

EDIT - Keep in mind that this will only search in the first level of the tree. If the item you're looking for is placed somewhere deeper, you'll have to do a recursive search. At that point, maybe just keeping the values stored somewhere from the start would be better.

Upvotes: 1

lamorach
lamorach

Reputation: 89

I believe .Contains() would check for the value by reference since it isn't a simple string object. This requires you to iterate through each of the items until you retrieve the item which matches the header.

LINQ Example

    if (MyTreeView.Items.Cast<TreeViewItem>().Any(item => item.Header.ToString() == @"C:\"))
    {
       MessageBox.Show(@"Tree contains C:\");
    }

Upvotes: 4

Related Questions