Winforms数据绑定到控件的可见属性

7

当将数据绑定到控件的可见属性时,是否存在已知问题?

无论我的属性是什么,该控件始终不可见。

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

我尝试了控件的文本属性和其他属性,它们似乎都能正常工作。

我正在尝试设置面板的可见属性。


你是如何绑定数据的?使用BindingSource控件还是声明式绑定? - matt eisenberg
这可能与这个有关:https://dev59.com/mXE85IYBdhLWcg3w9onw#2570153 - Marwie
6个回答

8
我发现,如果你认为绑定控件的Visible属性是有问题的,那么生活会更好,尽管有时它确实能正常工作。请参见http://support.microsoft.com/kb/327305,其中提到了这一点(虽然KB文章适用于.NET 1.0和1.1,但至少在2.0中仍然存在该问题)。
我创建了一个实用类来创建绑定,其中包括一个集中处理解决方法的地方。它不是在Visible上实际创建绑定,而是做了两件事情:
1. 它订阅数据源的INotifyPropertyChanged.PropertyChanged事件,并在事件被触发时根据需要设置Visible值。 2. 根据当前数据源值设置Visible的初始值。
这需要一些反射代码,但并不太糟糕。关键是不要同时绑定Visible属性和执行解决方法,否则它将无法正常工作。

6

解决方法:在BindingComplete事件上设置Visible属性。

我遇到了同样的问题,设置标签的Visible属性总是保持为false,尽管设置Enabled属性工作正常。


5

我在.NET 4.7.1和Visual Studio 2017中遇到了这个问题。为了解决它,我将我的控件的Visible属性初始设置为True,因为之前它是False


哇,这个可行,非常感谢!我将来会在每个控件上尝试一下 :P - Issung

1

需要检查的事项:

  • 确保已经实例化了具有IsRibbonCategory属性的类
  • 您是否将绑定源的数据源属性设置为该类的实例
  • 数据源更新模式应为“在验证时”
  • 确保您没有手动将控件的可见属性设置为false

希望这可以帮助您。您能发布更多代码吗?


我已经检查了所有这些,但都不行。有一个问题,你尝试过将数据绑定到可见属性并且它起作用了吗? - B Z
是的。VS 2008/Winforms。您使用哪个事件来设置Bindingsource控件的数据源? - matt eisenberg
你尝试在窗体的加载事件中调用bindingsource.CurrencyManager.Refresh了吗? - matt eisenberg
不,那行不通。我会尝试组合一个小型原型。 - B Z

0
一个解决方法是使用一个组件来绑定控件的可见性属性,而不是直接绑定到控件的可见性属性。请参考下面的代码:
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);
        }
    }
}

}


0
这是我的解决方案,可能很愚蠢,但它已经成功运行了很多次。
我在表单中放置了一个Panel控件,并将其设置为填充整个表单,然后将所有控件都放在该Panel中。我绑定了Visible属性的所有控件都会根据DataGridView中的对象而改变它们的可见性。

Form structure


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接