Search code examples
c#winformscheckboxtreeviewnodes

How can I disable a treenode checkbox?


I am using treeviewExtensions from codeproject which implements some iEnumerable recursion so that all parent and child nodes get checked when a node is checked.

Next I want to implement a way for me to disable a specific node. I have indicated through GUI that a node is unavailable by setting the color to gray. However, the checkbox next to the node is still Enabled and there is no disable/enable property. Any way I can get around this?

Example of Node10 not being disabled


Solution

  • You didn't specify exactly what you want if a TreeNode is disabled. Do you only want some special colouring, or do you want something with the Checked state and the subnodes if a TreeNode becomes disabled?

    So you want a TreeNode with some special behaviour?

    In you OO class you learned that if you want something that has almost the same behaviour as something else, you should consider to derive one from another.

    class TreeNodeThatCanBeDisabled : TreeNode // TODO: invent proper name
    {
        // Coloring when enabled / disabled
        public Color EnabledForeColor {get; set;} = base.ForeColor;
        public Color EnabledBackColor {get; set;} = base.BackColor;
        public Color DisabledForeColor {get; set;} = ...
        public Color DisabledBackColor {get; set;} = ...
    
        private bool isEnabled = true;
    
        public bool IsEnabled
        {
            get => this.isEnable;
            set
            {
                it (this.IsEnabled = value)
                {
                    // TODO: set the colors
                    this.isEnabled = value;
                }
            }
        }
    }
    

    Maybe you want to raise an event when IsEnabled changes, I'm not sure whether it is wise to do this per node:

    public event EventHandler IsEnabledChanged;
    protected virtual void OnEnabledChanged(EventHandle e)
    {
        this.IsEnabledChanged?.Invoke(this, e);
    }
    

    Call this in IsEnabled Set.

    Furthermore: what do you want with the checkmark? And should all subNodes also be disabled?

    foreach (TreeNodeThatCanBeDisabled subNode in this.Nodes.OfType<TreeNodeThatCanBeDisabled())
    {
        subNode.IsEnabled = value;
    }
    

    And I think you should create a TreeNodeView that can enable / disable several TreeNodes at a time, and that can give you all Enabled / Disabled nodes.

    TODO: decide whether this special TreeNodeView may contain only TreeNodesThatCanBeDisabled, or also standard TreeNodes.

    class TreeNodeViewThatCanHoldTreeNodesThatCanBeDisabled : TreeNodeView // TODO: proper name
    {
        // Coloring when enabled / disabled
        public Color EnabledForeColor {get; set;} = base.ForeColor;
        public Color EnabledBackColor {get; set;} = base.BackColor;
        public Color DisabledForeColor {get; set;} = ...
        public Color DisabledBackColor {get; set;} = ...
    
        public void AddNode(TreeNodeThatCanBeDisabled treeNode)
        {
            this.Nodes.Add(treeNode);
        }
    
        public IEnumerable<TreeNodeThatCanBeDisabled> TreeNodesThatCanBeDisabled =>
            base.Nodes.OfType<TreeNodeThatCanBeDisabled>();
    
        public IEnumerable<TreeNodeThatCanBeDisabled> DisabledNodes =>
            this.TreeNodesThatCanBeDisabled.Where(node => !node.IsEnabled);
    
        public void DisableAll()
        {
            foreach (var treeNode in this.TreeNodesThatCanBeDisabled)
                treeNode.Enabled = false;
        }
    

    TODO: do you only want to change the colors? or also the Checkbox? Collapse / Expand? Maybe an event that tells you: "hey buddy, this treeNode has become disabled"?

    And what if someone clicks on a disabled TreeNode. Should it still collapse / expand, or should it stay in the state that it is:

    protected override void OnBeforeExpand (System.Windows.Forms.TreeViewCancelEventArgs e)
    {
        if (e.Node is TreeNodeThatCanBeDisabled treeNode)
        {
            // cancel expand if not enabled:
            if (!treeNode.IsEnabled)
               e.Cancel = true;
        }
    }
    

    Similar for collapse?