Toadums
Toadums

Reputation: 2812

How to add checkboxes to a treeview with dynamic ItemsSource?

So I have tried a whole bunch of examples from google, but I cannot seem to give my treeview checkboxes....The only thing I can think of is that it is because my tree's ItemsSource is always changing

An example I was trying is: TreeView with Checkboxes

most noteable, the HierarchicalDataTemplate:

<HierarchicalDataTemplate 
  x:Key="CheckBoxItemTemplate"
  ItemsSource="{Binding Children, Mode=OneTime}"
  >
  <StackPanel Orientation="Horizontal">
    <!-- These elements are bound to a FooViewModel object. -->
    <CheckBox
      Focusable="False" 
      IsChecked="{Binding IsChecked}" 
      VerticalAlignment="Center"
      />
    <ContentPresenter 
      Content="{Binding Name, Mode=OneTime}" 
      Margin="2,0"
      />
  </StackPanel>
</HierarchicalDataTemplate> 

and I set my tree's ItemTemplate to:

ItemTemplate="{StaticResource CheckBoxItemTemplate}"

But I see no checkboxes. I think it is because in the example, the data is bound to Children...but in my example, I am always changing the itemsSource (moving from tree to tree, or editting it, and adding it back to the tree etc)...

Anyone know how to make it work?

Thanks!

*EDIT*

adding the treeview itemsSource I just go

tv_master.ItemsSource = t.TreeItems;

Where the t.TreeItems is a List which holds the top level nodes..

my treeview:

<my:SpecTreeView Margin="8,8,0,12" 
                         x:Name="tv_local" 
                         TreeViewItem.Selected="node_Selected" HorizontalAlignment="Left" Width="304"
                         x:FieldModifier="private" BorderBrush="Black">

The original class used by the person who wrote the checkbox code:

using System.Collections.Generic;
using System.ComponentModel;

namespace TreeViewWithCheckBoxes
{
    public class FooViewModel : INotifyPropertyChanged
    {
        #region Data

        bool? _isChecked = false;
        FooViewModel _parent;

        #endregion // Data

        #region CreateFoos

        public static List<FooViewModel> CreateFoos()
        {
            FooViewModel root = new FooViewModel("Weapons")
            {
                IsInitiallySelected = true,
                Children =
                {
                    new FooViewModel("Blades")
                    {
                        Children =
                        {
                            new FooViewModel("Dagger"),
                            new FooViewModel("Machete"),
                            new FooViewModel("Sword"),
                        }
                    },
                    new FooViewModel("Vehicles")
                    {
                        Children =
                        {
                            new FooViewModel("Apache Helicopter"),
                            new FooViewModel("Submarine"),
                            new FooViewModel("Tank"),                            
                        }
                    },
                    new FooViewModel("Guns")
                    {
                        Children =
                        {
                            new FooViewModel("AK 47"),
                            new FooViewModel("Beretta"),
                            new FooViewModel("Uzi"),
                        }
                    },
                }
            };

            root.Initialize();
            return new List<FooViewModel> { root };
        }

        FooViewModel(string name)
        {
            this.Name = name;
            this.Children = new List<FooViewModel>();
        }

        void Initialize()
        {
            foreach (FooViewModel child in this.Children)
            {
                child._parent = this;
                child.Initialize();
            }
        }

        #endregion // CreateFoos

        #region Properties

        public List<FooViewModel> Children { get; private set; }

        public bool IsInitiallySelected { get; private set; }

        public string Name { get; private set; }

        #region IsChecked

        /// <summary>
        /// Gets/sets the state of the associated UI toggle (ex. CheckBox).
        /// The return value is calculated based on the check state of all
        /// child FooViewModels.  Setting this property to true or false
        /// will set all children to the same check state, and setting it 
        /// to any value will cause the parent to verify its check state.
        /// </summary>
        public bool? IsChecked
        {
            get { return _isChecked; }
            set { this.SetIsChecked(value, true, true); }
        }

        void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
        {
            if (value == _isChecked)
                return;

            _isChecked = value;

            if (updateChildren && _isChecked.HasValue)
                this.Children.ForEach(c => c.SetIsChecked(_isChecked, true, false));

            if (updateParent && _parent != null)
                _parent.VerifyCheckState();

            this.OnPropertyChanged("IsChecked");
        }

        void VerifyCheckState()
        {
            bool? state = null;
            for (int i = 0; i < this.Children.Count; ++i)
            {
                bool? current = this.Children[i].IsChecked;
                if (i == 0)
                {
                    state = current;
                }
                else if (state != current)
                {
                    state = null;
                    break;
                }
            }
            this.SetIsChecked(state, false, true);
        }

        #endregion // IsChecked

        #endregion // Properties

        #region INotifyPropertyChanged Members

        void OnPropertyChanged(string prop)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}

My TNode Class

public class TNode : TreeViewItem{

    public int Level { get; set; }
    public Boolean IsCheckedStr { get; set; }
    public string Section { get; set; }
    public string Note { get; set; }
    public Boolean Locked { get; set; }
    public string ID { get; set; }
    public int Hierarchy { get; set; }
    public string Type { get; set; }
    public Boolean HasChildren { get; set; }
    public string TextBlock { get; set; }
    public Boolean ShowDetails { get; set; }
    public List<TNode> Dependencies { get; set; }
    public TNode(string id) {
        ID = id;
        Dependencies = new List<TNode>();
    }

I just want to get the checkboxes to appear for now :(

Let me know if there is anything else you would like to see

Upvotes: 0

Views: 3106

Answers (1)

brunnerh
brunnerh

Reputation: 184376

Edit: DataTemplates are for data, TreeViewItems or subclasses thereof are not data, the template will be ignored. You should see an error regarding this in the Output-window of Visual Studio (which is helpful for debugging databinding issues of any sort).


See nothing wrong with this, you might want to post the code behind for the classes, and the TreeView instance declaration.

A common error is the lack of notifying interfaces. Also: Did you bind the ItemsSource of the TreeView itself to a root-list of items?

Upvotes: 1

Related Questions