views:

711

answers:

2

I implemented a WPF load-on-demand treeview like described in this (very good) article. In the mentioned solution a dummy element is used to preserve the expand + icon / treeview item behavior. The dummy item is replaced with real data, when the user clicks on the expander.

I want to refine the model by adding a property public bool HasChildren { get { ... } } to my backing TreeNodeViewModel.

Question:
How can I bind this property to hide/show the expand icon (in XAML)? I am not able to find a suitable trigger/setter combination.
(INotifyPropertyChanged is properly implemented.)

Thanks for your time.

Update 1:
I want to use my property public bool HasChildren instead of using the dummy element.
Determining whether or not an item has children is somewhat costly, but still much cheaper than fetching the children.

A: 

After quickly looking into Josh's code, I found this constructor:

protected TreeViewItemViewModel(TreeViewItemViewModel parent, bool lazyLoadChildren)
{
    _parent = parent;

    _children = new ObservableCollection<TreeViewItemViewModel>();

    if (lazyLoadChildren)
        _children.Add(DummyChild);
}

So, if you pass false for the lazyLoadChildren parameter from your inheriting ViewModel classes, the + icon should not appear because the DummyChild is not added. Since you seem to know whether your items have children or not, you should be able to pass the appropriate value for the lazyLoadChildren property. Or am I missing something?

gehho
A: 

Julian,

this is a really good question. Why don't you try to write your own tree view item? :) I mean, not from the scratch, just derive from existing TreeViewItem and add your property. I have prepared a quick sample, but feel free to modify it as you wish (and ask questions if something is not perfectly clear). here we go:

public class TreeViewItem_CustomControl : TreeViewItem
{
    static TreeViewItem_CustomControl()
    {
        HasChildrenProperty = DependencyProperty.Register("HasChildren", typeof(Boolean), typeof(TreeViewItem_CustomControl));
    }

    static DependencyProperty HasChildrenProperty;

    public Boolean HasChildren
    {
        get
        {
            return (Boolean)base.GetValue(HasChildrenProperty);
        }

        set
        {
            if (value)
            {
                if (this.Items != null)
                {
                    this.Items.Add(String.Empty); //Dummy item
                }
            }
            else
            {
                if (this.Items != null)
                {
                    this.Items.Clear();
                }
            }

            base.SetValue(HasChildrenProperty, value);
        }

    }
}

This was the code for your custom TreeViewItem. Now let's use it in XAML:

<TreeView>
    <TreeViewItem Header="qwer">
        Regulat tree view item.
    </TreeViewItem>
    <CustomTree:TreeViewItem_CustomControl x:Name="xyz" Header="temp header" Height="50">
        <TreeViewItem>Custom tree view item, which will be removed.</TreeViewItem>
    </CustomTree:TreeViewItem_CustomControl>
</TreeView>

As you can see, first item is a regular one and the second is your custom one. Please note, that it has one child. Next, you can bind HasChildren property to some Boolean object in your ViewModel or just simply test my custom class by setting HasChildren to False from code behind the above XAML:

xyz.HasChildren = false;

Now, despite your element has one child, expand button is not displayed, so it means, that my custom class works.

I hope I helped you, but feel free to ask if you have any questions.

Piotr.

Piotr Justyna