7

Are there any known issues when databinding to a control's visible property?

The control is always NOT visible regardless of what my property is.

Public ReadOnly Property IsRibbonCategory() As Boolean
    Get
        Return True
    End Get
End Property

I tried the control's text property and other properties and they seem to work correctly.

I am trying to set a Panel's visible property.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
B Z
  • 9,363
  • 16
  • 67
  • 91

6 Answers6

8

I've found that life is better if you assume that binding to a control's Visible property is broken, despite the fact that it sometimes works. See http://support.microsoft.com/kb/327305, which says as much (and while the KB article applies to .NET 1.0 and 1.1, it still seems to be a problem in at least 2.0).

I created a utility class for creating bindings which, among other things, gave me a centralized place to add a work-around. Instead of actually creating a binding on Visible it does two things:

  1. It subscribes to the data source's INotifyPropertyChanged.PropertyChanged event and sets the Visible value as appropriate when the event is raised.
  2. It sets the initial value of Visible according to the current data source value.

This required a little reflection code, but wasn't too bad. It is critical that you don't bind the Visible property and do the work-around or it won't work.

Eric Smith
  • 2,739
  • 2
  • 30
  • 29
6

Workaround: Set the Visible property on the BindingComplete event.

I had same issue setting a label's Visible property - always stays false, even though setting the Enabled property works fine.

David Russell
  • 623
  • 6
  • 16
5

I just hit this issue in .NET 4.7.1 and Visual Studio 2017. To fix it, I changed the Visible property on my control to be initially set to True, as I had it as False previously.

AndrewL
  • 3,126
  • 5
  • 31
  • 33
1

Things to check:

  • Be sure you've instantiated the class that has the IsRibbonCategory property
  • Did you set the datasource of property of the binding source to the instance of the class
  • The datasource update mode should be on "on validation"
  • Make sure you didn't set the visible property manually to false on the control

Hope that helps. Can you post more code?

matt eisenberg
  • 183
  • 6
  • 21
0

Here is my turn around, it may be stupid but it worked many times.

I put one Panel control in my form, I make it to Fill my form and I put everything in that Panel. All the controls I bind the Visible property see their visibility change according to the objects in my DataGridView.

Form structure

Fabrice T
  • 648
  • 9
  • 23
0

A workaround would be to use a Component to databind to a control's visiblity property instead of directly binding to the control's visibility property. See below code:

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication2
{
  public class ControlVisibilityBinding : Component
  {
    private static readonly object EventControlChanged = new object();
    private static readonly object EventVisibleChanged = new object();

    private System.Windows.Forms.Control _control;
    private bool _visible = true;

    public event EventHandler VisibleChanged
    {
        add { Events.AddHandler(EventVisibleChanged, value); }
        remove { Events.RemoveHandler(EventVisibleChanged, value); }
    }

    public event EventHandler ControlChanged
    {
        add { Events.AddHandler(EventControlChanged, value); }
        remove { Events.RemoveHandler(EventControlChanged, value); }
    }

    public ControlVisibilityBinding()
    {
    }

    public ControlVisibilityBinding(IContainer container)
    {
        container.Add(this);
    }

    [DefaultValue(null)]
    public System.Windows.Forms.Control Control
    {
        get { return _control; }
        set
        {
            if(_control == value)
            {
                return;
            }
            WireControl(_control, false);
            _control = value;
            if(_control != null)
            {
                _control.Visible = _visible;
            }
            WireControl(_control, true);
            OnControlChanged(EventArgs.Empty);
            OnVisibleChanged(EventArgs.Empty);
        }
    }

    [DefaultValue(true)]
    public bool Visible
    {
        get { return _visible; }
        set
        {
            if(_visible != value)
            {
                _visible = value;
            }
            if(Control != null)
            {
                Control.Visible = _visible;
            }
            OnVisibleChanged(EventArgs.Empty);
        }
    }

    private void WireControl(Control control, bool subscribe)
    {
        if(control == null)
        {
            return;
        }
        if(subscribe)
        {
            control.VisibleChanged += Control_VisibleChanged;
        }
        else
        {
            control.VisibleChanged -= Control_VisibleChanged;
        }
    }

    private void Control_VisibleChanged(object sender, EventArgs e)
    {
        OnVisibleChanged(EventArgs.Empty);
    }

    protected virtual void OnVisibleChanged(EventArgs e)
    {
        EventHandler subscribers = (EventHandler)Events[EventVisibleChanged];
        if(subscribers != null)
        {
            subscribers(this, e);
        }
    }

    protected virtual void OnControlChanged(EventArgs e)
    {
        EventHandler subscribers = (EventHandler)Events[EventControlChanged];
        if(subscribers != null)
        {
            subscribers(this, e);
        }
    }
}

static class Program
{
    [STAThread]
    static void Main()
    {
        using(Form form = new Form())
        using(FlowLayoutPanel groupBoxLayoutPanel = new FlowLayoutPanel())
        using(RadioButton visibleButton = new RadioButton())
        using(RadioButton hiddenButton = new RadioButton())
        using(GroupBox groupBox = new GroupBox())
        using(Label text = new Label())
        using(ControlVisibilityBinding visibilityBinding = new ControlVisibilityBinding())
        using(TextBox inputTextBox = new TextBox())
        {
            groupBoxLayoutPanel.Dock = DockStyle.Fill;
            groupBoxLayoutPanel.FlowDirection = FlowDirection.LeftToRight;
            groupBoxLayoutPanel.AutoSize = true;
            groupBoxLayoutPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;

            visibleButton.Text = "Show Label";
            visibleButton.AutoSize = true;
            hiddenButton.Text = "Hide Label";
            hiddenButton.AutoSize = true;
            groupBoxLayoutPanel.Controls.Add(visibleButton);
            groupBoxLayoutPanel.Controls.Add(hiddenButton);

            inputTextBox.Text = "Enter Label Text Here";
            inputTextBox.Dock = DockStyle.Top;

            groupBox.AutoSize = true;
            groupBox.AutoSizeMode = AutoSizeMode.GrowAndShrink;
            groupBox.Controls.Add(groupBoxLayoutPanel);
            groupBox.Dock = DockStyle.Fill;

            text.AutoSize = true;
            text.ForeColor = Color.Red;
            text.Dock = DockStyle.Bottom;
            text.BorderStyle = BorderStyle.FixedSingle;
            text.Font = new Font(text.Font.FontFamily, text.Font.Size * 1.25f, FontStyle.Bold | FontStyle.Italic);
            text.DataBindings.Add("Text", inputTextBox, "Text", true, DataSourceUpdateMode.Never);

            visibilityBinding.Control = text;
            visibleButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
            Binding binding = hiddenButton.DataBindings.Add("Checked", visibilityBinding, "Visible", true, DataSourceUpdateMode.OnPropertyChanged);
            ConvertEventHandler invertConverter = (sender, e) => e.Value = !((bool)e.Value);
            binding.Format += invertConverter;
            binding.Parse += invertConverter;

            form.Controls.Add(inputTextBox);
            form.Controls.Add(text);
            form.Controls.Add(groupBox);
            Application.Run(form);
        }
    }
}

}

Jacob Seleznev
  • 8,013
  • 3
  • 24
  • 34
Hasani Blackwell
  • 2,026
  • 1
  • 13
  • 10